В настоящее время я пишу оболочку C # для API C ++, но определенная структура и функция, которая опирается на эту структуру, выдают очень странные ошибки при отладке.
C ++ Struct:
typedef struct
{
unsigned __int handle;
char name[80];
unsigned int unique_ID;
} DeviceInfo;
Затем следует эта функция:
int __stdcall get_device_info(DeviceInfo di[], const int length_of_di_array, int* p_numValidDevices);
Структура и функция импортируются следующим образом:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DeviceInfo
{
public UInt32 handle;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 80)]
public String name;
public UInt32 unique_ID;
}
[DllImportAttribute("MyC++API.dll", EntryPoint = "get_device_info", CallingConvention = CallingConvention.StdCall)]
public static extern int get_device_info(ref DeviceInfo di, int length_of_di_array, ref numValidDevices);
Предполагаемое использование этой структуры и функции - просто получить некоторую информацию об устройстве.с доски доступа.В настоящее время у меня нет доступа к телу функции в C ++, поэтому я могу только предположить, что она работает на 100% (работает нормально в C ++).
Проблема заключается в том, что при использовании функции для запуска через массивструктуры, он выводит данные, которые я ищу, но также начнет сбой во время выполнения, предоставляя мне различные окна ошибок.
C # код:
static void Main()
{
int numValidDevices = 0; //initialize variable
DeviceInfo[] di = new DeviceInfo[16]; //max of 16 devices
for (int i = 0; i < numValidDevices; ++i) //sorts through all validated devices
{
rc = get_device_info(ref di[i], 16, ref numValidDevices); //accesses each device element and returns the data
Console.WriteLine("Handle: {0}\nName: {1}\nUnique ID: {2}", di[i].handle, di[i].name, di[i].unique_ID);
}
Console.ReadLine(); //stops console from closing prematurely
API_close(); //custom close function from the C++ API
}
Ошибки при отладке (информацияпо-прежнему отображается): «Произошло необработанное исключение типа« System.Threading.ThreadStateException »в System.dll
Дополнительная информация: поток не был запущен."
"Необработанное исключениетипа «System.ExecutionEngineException» возникла в mscorlib.dll »
Ошибка при отладке (информация не отображается, программа не выполняется):« Произошло необработанное исключение типа «System.AccessViolationException» в mscorlib.dll
Дополнительная информация: Попытка чтения или записи в защищенную память. Это часто свидетельствует о повреждении другой памяти. "
При закрытии окна консоли: «Инструкция в« 0x7c9113c0 »ссылается на память в« 0x00000000 ».Память не может быть «записана». »(Иногда говорится« прочитано »вместо« записано »).
Я провел много исследований по PInvoke и наткнулся на приложение Microsoft InteropAssistant , различные статьи о переполнении стека, такие как , эта и эта публикация , кажется даже ближе к тому, что я делаю, но я все еще копаюсь в том, как использовать Marshal.CoTaskMemAlloc /Освободите, и посмотрите, будет ли это вообще что-нибудь делать ...
Пока то, что у меня есть для моей структуры и функции, верно, я попытался изменить структуру, чтобы использовать IntPtr, но это не возвращает di.name значение и di.unique_ID становится бестолковым (как ни странно, di.handle остается в силе)
C # код:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DeviceInfo
{
public UInt32 handle;
IntPtr p_name;
public String name { get { return Marshal.PtrToStringAnsi(p_name); } }
public UInt32 unique_ID;
}
Предполагаемый вывод:
Handle: 3126770193
Name: DEVICE_A
Unique ID: 12345678
Выходные данные IntPtr:
Handle: 3126770193
Name:
Unique ID: 1145128264
Как ни странно, использование IntPtr не приводит ни к одной из вышеперечисленных ошибок и работает нормально. Это приводит меня к мысли, что проблема заключается в маршалинге над символом C ++ в строку, но яЯ не уверен, что проблема заключается вмаршалинг, управление памятью (нет?) или что-то, что я не уловил полностью.
Любая и вся обратная связь была бы очень признательна, я был озадачен этим несколько недель назад...