#c_sharp #cpp #dll
К проекту на 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.
Какие могут быть причины и как исправить?
Ответы
Ответ 1
Причины могут быть разные: Ошибка в реализации нативной функции. Чтобы её исключить, попробуйте сделать пустую GetSets и пересобрать DLL. Проблемы совместимости DLL и С# кода. Был случай, когда DLL, собранная в C++Builder приводила к ошибкам на стадии выполнения. Пересборка компилятором MS решила проблему на корню. Неправильно передаются аргументы в функцию. См. маршалинг строк. Если сигнатура нативной функции содержит сложные типы из стандартной библиотеки C++ (в том числе и std::string), использовать такую функцию в P/Invoke будет проблематично (читай как невозможно). Разные компиляторы по-разному реализуют стандартные классы, поэтому передавать между модулями такие типы довольно опасно. В данном случае наиболее правильное решение будет заключаться в том, чтобы экспортировать функцию, принимающую const char* (си-строку), а дальше в потрохах DLL уже можно использовать и std::string для удобства.Ответ 2
Проблем тут несколько, одна из которых — возвращаемое значение из нативной функции (std::string). В двух словах — стандартными методами вам не вернуть строку из нативного метода результатом. Вторая проблема — строки в C# имеют кодировку Unicode, а нативная std::string имеет кодировку ASCII. Советую использовать std::wstring в нативном методе, CharSet = CharSet.Unicode в маршаллинге и возвращать результат как показано тут: «Return a std::wstring from C++ into C#», «Passing strings from C# to C++ dll and back — minimal example». P. S. С C++ CLI все намного лучше в плане маршаллинга.
Комментариев нет:
Отправить комментарий