Обновление
После просмотра обновленного вопроса, различных комментариев и кода вашей нативной функции, вероятно, возникает исключение при вызове check_hardware_stuff()
.Это достаточно просто для отладки.Я бы заменил вашу функцию на такую:
unsigned char versionString [50];
__declspec(dllexport) unsigned char* Version_String()
{
strcpy(versionString, "testing");
return versionString;
}
Если это не помогло, то я предполагаю, что ошибка возникает в DllMain
вашей DLL.Отладьте это, поместив вышеуказанную функцию в простую ванильную DLL, которая больше ничего не делает.
Оригинальный ответ
Соглашение о вызовах является наиболее очевидной проблемой.Ваш нативный код, скорее всего, использует cdecl
, но по умолчанию p / invoke - stdcall
.Измените свою подпись p / invoke, чтобы она была такой:
[DllImport("BSL430.dll", CallingConvention=CallingConvention.Cdecl)]
public extern static IntPtr Version_String();
Вы можете спокойно пропустить параметр CharSet
, поскольку ни один из параметров не имеет текста, поскольку вы возвращаете возвращаемое значение как указатель.
Редактировать: Ганс правильно указывает в комментариях, что, поскольку нет параметров, несоответствие соглашения о вызовах не имеет значения.Так что это не проблема.
Вызовите Marshal.PtrToStringAnsi
для преобразования в строку .net.
string version = Marshal.PtrToStringAnsi(Version_String());
Поскольку PtrToStringAnsi
ожидает IntPtr
параметр Я бы порекомендовал вам использовать IntPtr
в качестве типа возврата вашей подписи p / invoke.
Все это предполагает, что память, возвращаемая из вашей нативной функции, выделяется и освобождается в нативной DLL.Если он выделен в куче, и вы ожидаете, что вызывающая сторона освободит его, то у вас небольшая проблема.Как вы освобождаете память из C #, поскольку у вас нет доступа к куче встроенной библиотеки DLL?
Простое решение состоит в использовании общей кучи COM для выделения памяти.Вызовите CoTaskMemAlloc
, чтобы выделить буфер для строки.Затем объявите возвращаемое значение типа string
, и маршаллер p / invoke освободит выделитель COM.
[DllImport("BSL430.dll", CallingConvention=CallingConvention.Cdecl)]
public extern static string Version_String();
...
string version = Version_String();
Конечно, это применимо только в том случае, если вы возвращаете выделенную память кучи, которую ожидаетевызывающая сторона для освобождения.