К проекту на C# подключаю библиотеку C++, библиотека полностью рабочая.
Руководство по подключению взял тут
[DllImport("C:\\Users\\Zaki\\Desktop\\SetsGen.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern string GetSets(string ids, int power);
public void DllSub(string param)
{
try
{
string myAns = GetSets(param, 3);
string[] tokens = myAns.Split('/');
foreach (var token in tokens)
{
Console.WriteLine(token);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Нативная сигнатура функции GetSets в Dll выглядит следующим образом:
std::string GetSets(std::string ids, int power)
Получаю исключение при обращении к портированной функции GetSets:
An unhandled exception of type 'System.AccessViolationException'
occurred in Test.exe
Additional information: Attempted to read or write protected memory.
This is often an indication that other memory is corrupt.
Какие могут быть причины и как исправить?
Ответ
Причины могут быть разные:
Ошибка в реализации нативной функции. Чтобы её исключить, попробуйте сделать пустую GetSets и пересобрать DLL.
Проблемы совместимости DLL и С# кода. Был случай, когда DLL, собранная в C++Builder приводила к ошибкам на стадии выполнения. Пересборка компилятором MS решила проблему на корню.
Неправильно передаются аргументы в функцию. См. маршалинг строк.
Если сигнатура нативной функции содержит сложные типы из стандартной библиотеки C++ (в том числе и std::string), использовать такую функцию в P/Invoke будет проблематично (читай как невозможно). Разные компиляторы по-разному реализуют стандартные классы, поэтому передавать между модулями такие типы довольно опасно.
В данном случае наиболее правильное решение будет заключаться в том, чтобы экспортировать функцию, принимающую const char* (си-строку), а дальше в потрохах DLL уже можно использовать и std::string для удобства.
Комментариев нет:
Отправить комментарий