#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 все намного лучше в плане маршаллинга.
Комментариев нет:
Отправить комментарий