Вопрос

Я создал 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, чтобы проверить, какие методы доступны

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top