2015-09-06 6 views
1

Я создал DLL-файл, который включает в себя две пустые функции ниже.stdcall вызов конвенции и использование pinvoke в C#

extern "C" __declspec(dllexport) void __stdcall myFunc1() { 
    // just empty function 
} 

extern "C" __declspec(dllexport) void __cdecl myFunc2() { 
    // just empty function 
} 

В C#, я мог вызывать функции с помощью DLLImport атрибута, как показано ниже.

[DllImport("myDLL", CallingConvention=CallingConvention.StdCall)] 
private extern static void myFunc1(); 

[DllImport("myDLL", CallingConvention=CallingConvention.Cdecl)] 
private extern static void myFunc2(); 

Так что я снова попытался непосредственно LoadLibrary() из kernel32.dll вместо DllImport атрибута.

[UnmanagedFunctionPointer(CallingConvention.StdCall)] 
private delegate void MyFunc1(); 

[UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
private delegate void MyFunc2(); 

Однако ошибка времени выполнения происходит, когда я звоню MyFunc1() где MyFunc2() работает.

Так что я заменил __stdcall на __cdecl на C++, перекомпилировал DLL, а затем снова вызвал MyFunc1() на C#.

И .. Это сработало.

Почему на земле не работает __stdcall вызов конвенции с pinvoke в C#?

+2

'DllImport' * есть * P/Invoke. Что вы пытаетесь сделать на земле? : D 'UnmanagedFunctionPointer' обрабатывает управляемый делегат как неуправляемый указатель функции (как следует из названия) - он не имеет ничего общего с вызовом неуправляемой функции в DLL. Хорошо, а не «ничего» - очевидно, у вас есть делегат, который вы можете передать или получить с неуправляемой стороны, но это не то, что вы пытаетесь сделать здесь. – Luaan

+1

Также, согласно документации для 'UnmanagedFunctionPointer',' если вы не указали имя поля, UnmanagedFunctionPointerAttribute игнорируется. '- Я не вижу, чтобы вы указали какое-либо имя. – Luaan

+0

Да, ты прав. На этот раз я использую LoadLibrary(), FreeLibrary() и GetProcAddress() для "kernel32.dll". Я не опубликовал остальную часть кода, потому что я думал, что это просто базовая вещь для опытных парней. – Jenix

ответ

6

Что происходит в том, что при переключении с __cdecl на __stdcall в код C++ компилятор украшает имя, с помощью которого функция экспортируется. Вместо myFunc1 он экспортируется как [email protected] или, возможно, [email protected]. Все равно, имя украшено. Вы можете проверить, что это так: dumpbin или средство просмотра зависимостей.

Когда вы вызываете GetProcAddress, он не может найти функцию с именем myFunc1 и поэтому возвращает NULL. Вы не проверяете возвращаемые значения и, следовательно, продолжаете независимо. Когда вы пытаетесь вызвать функцию, возникает ошибка времени выполнения.

Мне пришлось угадать большую часть этого, потому что вы не указали полный код. Другим большим уроком является проверка ошибок при вызове функций Win32.

+0

Спасибо, я проверю его, как вы сказали. Если причина заключается в украшении имен, что я могу сделать? Я думал, что ключевое слово extern «C» предотвратит проблемы, связанные с именованием. – Jenix

+2

Необходимо использовать def-файл для экспорта –

+0

Ну ладно, вижу, спасибо! – Jenix