Экспорт функций из C ++ dll в C # P /Invoke
Вопрос
Я создал C ++ dll, которую я хотел бы вызвать из C #-кода.Я могу вызвать одну функцию, но другая выдает исключение, когда код C # пытается загрузить dll.
Заголовок выглядит примерно так:
extern "C" __declspec(dllexport) BOOL Install();
extern "C" __declspec(dllexport) BOOL PPPConnect();
Это создает dll с немного запутанной таблицей экспорта (что означает foo = foo в поле name?):
File Type: DLL
Section contains the following exports for PPPManager.dll
00000000 characteristics
499F44F0 time date stamp Fri Feb 20 16:04:00 2009
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 000078E4 Install = Install
2 1 000079DC PPPConnect = PPPConnect
Мои объявления P / Invoke выглядят следующим образом:
[DllImport("PPPManager.dll")]
private static extern bool Install();
[DllImport("PPPManager.dll")]
private static extern bool PPPConnect();
Вызов Install возвращается без исключения, но когда я вызываю PPPConnect, я получаю исключение MISSINGMETHOD - "Не удается найти точку входа 'PPPConnect' в библиотеке DLL PInvoke 'PPPManager.dll "."
Я попытался удалить директивы extern и declspec из объявления функции Install, так что PPPConnect является единственной экспортируемой функцией, и это по-прежнему не позволяет мне вызывать PPPConnect.
Я также попытался выполнить DllImport по порядковому номеру;это дает тот же результат, что и вызов по имени - возвращает Install, но PPPConnect выдает исключение "Не удается найти точку входа '#2' ...".
Журнал взаимодействия дает:
[pinvokeimpl][preservesig]
bool invivodata.Common.System.IPAQUtils::Install();
BOOLEAN (I1_WINBOOL_VAL) Install();
JIT ERROR FOR PINVOKE METHOD (Managed -> Native):
[pinvokeimpl][preservesig]
bool invivodata.Common.System.IPAQUtils::PPPConnect();
BOOLEAN (I1_WINBOOL_VAL) PPPConnect();
Это выходит далеко за рамки моей компетенции, поэтому я приветствую любые предложения или мысли.
Спасибо, Пол
Редактировать:Оказывается, что этот код действительно работает;проблема заключалась в том, что последняя версия dll не распространялась на устройство.Д'о!
Решение
Используете ли вы файл .def в своем dll-проекте для экспорта этих функций?Если это так, удалите его и повторите попытку.Это всего лишь предположение, потому что похоже, что ваш экспорт не такой, каким он должен быть, когда вы выполняете extern "C" declspec(dllexports).
Я попробовал это с помощью простой C ++ dll, используя
extern "C" __declspec(dllexport) BOOL Install();
extern "C" __declspec(dllexport) BOOL PPPConnect();
и простое приложение на C #, использующее ваши объявления PInvoke и это сработало нормально.
Когда я сделал dumpbin / exports в dll, я увидел:
Дамп файла PPPManager.dll
Тип файла:DLL - ФАЙЛ
Раздел содержит следующие экспортные данные для PPPManager.dll
00000000 characteristics
499F6C2D time date stamp Fri Feb 20 20:51:25 2009
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 000110CD Install = @ILT+200(_Install)
2 1 00011069 PPPConnect = @ILT+100(_PPPConnect)
Обратите внимание, что экспортированные имена в моем случае отличаются.
Другие советы
Это может быть что-то столь же простое, как PPPConnect
сбой таким образом, что ОС неправильно интерпретирует его.Попробуйте реализовать оба варианта Install
и PPPConnect
как no-ops (просто попросите их вернуться TRUE
не делая ничего другого) и посмотрите, сохраняется ли ошибка.Если это так, попробуйте поменять местами порядок, в котором они экспортируются (по-прежнему без операций), и посмотрите, связана ли проблема с упорядочением (маловероятно) или с чем-то другим.
Вы также можете использовать графический инструмент depends
чтобы подтвердить, как выглядит таблица экспорта DLL, но я сомневаюсь, что проблема исходит из этих источников.
Согласно вашему описанию Install и PPPConnect отличаются только названиями.Я предполагаю, что вы просто используете старую .версию dll с вашим приложением на C #.Единица без определенного PPPConnect.
Декларации выглядят правильно (насколько я могу судить без источников).
Отличная информация, но, как вы упомянули, здесь все в порядке.Попробуйте установить средства отладки для Windows и запустить:
kd -z \path\to\PPPManager.dll -y \path\to\PPPManager.pdb -c "x pppmodule!*"
чтобы получить лучший дамп таблицы символов;это тоже выстрел вслепую, но вы также могли бы попробовать:
extern "C"
{
__declspec(dllexport) BOOL Install();
__declspec(dllexport) BOOL PPPConnect();
};
на случай, если __declspec делает что-то странное.
используйте dependency walker и откройте вашу DLL, чтобы проверить, какие методы доступны