Я пытаюсь использовать C ++ DLL (сторонняя библиотека, реализующая протокол EMI, с доступным исходным кодом) в .NET.Я успешно выполнил маршаллинг, вызывал функции и заставлял все работать нормально.
Проблема возникает, когда я хочу сделать маршаллинг из IntPtr обратно в .NET Struct, вот код (измененный как предложено - удалено)ref "и изменил AllocHGlobal для выделения только размера emiStruct):
private EMI emiStruct;
private IntPtr emiIntPtr;
emiIntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(emiStruct));
Marshal.StructureToPtr(emiStruct, emiIntPtr, false);
EMIStruct.Error result = emi_init(emiIntPtr, hostname, portNumber, password, shortNumber, windowSize, throughput);
Marshal.PtrToStructure(emiIntPtr, emiStruct);
Последняя строка (PtrToStructure) вызывает исключение" Попытка чтения или записи защищенной памяти. Это часто указывает на то, что другая памятькоррумпированы».
Кроме того, я вижу выходные данные отладки:
A first chance exception of type 'System.AccessViolationException' occurred in mscorlib.dll
First-chance exception at 0x7c970441 in XXXXX.exe: 0xC0000005: Access violation reading location 0xc3fffff8.
First-chance exception at 0x7c970441 in XXXXX.exe: 0xC0000005: Access violation reading location 0x01fffff7.
First-chance exception at 0x7c970441 in XXXXX.exe: 0xC0000005: Access violation reading location 0x00001f1d.
Я предполагаю, что проблема заключается в выделении памяти для указателя emiIntPtr.Несмотря на то, что когда я запускаю код и возникает проблема с подключением к серверу (например, сервер не найден), последующая сортировка в Struct emiStruct выполняется правильно (без исключения).Проблема возникает только тогда, когда соединение успешно установлено и сервер отправляет ответ.
Кроме того, я написал пример приложения на C ++, используя ту же библиотеку DLL, которую я пытаюсь использовать в .NET, и это приложение (когдаЯ компилирую это) работает просто отлично - это значит, что C ++ DLL должна быть в порядке и не вызывать сбоев.
Кроме того, я нашел несколько советов, чтобы проверить / снять галочку с нескольких свойств для компилятора проекта (используя JIT,скомпилируйте его для процессора x86 и т. д.), к сожалению, ничего из этого не помогло.
Есть ли у вас какие-либо предположения о том, где может быть проблема или как сделать правильную инициализацию IntPtr в .NET и сопоставление между IntPtr и Struct??
Спасибо всем за ваши ответы:
Здесь я добавляю заголовок C ++ функции emi_init:
FUNC( init)( EMI* emi, /* out */
const char* hostname, /* in */
unsigned short port, /* in */
const char* password, /* in */
const char* origin_addr, /* in */
int window_sz, /* in */
int throughput); /* in */
А вот объявление C # emi_init (IВы удалили атрибут «ref» для emiPtr, как было предложено):
[System.Runtime.InteropServices.DllImport("emi.dll", EntryPoint = "_emi_init")]
public static extern EMIStruct.Error emi_init(
System.IntPtr emiPtr,
[System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string hostname,
ushort port,
[System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string password,
[System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] string origin_addr,
int window_sz, int throughput);
Однако все равно получаю то же исключение.