Экспорт функций из C ++ DLL в C # P / Invoke - PullRequest
8 голосов
/ 21 февраля 2009

Я создал C ++ dll, который я хотел бы вызвать из кода C #. Я могу вызвать одну функцию, но другая выдает исключение, когда код C # пытается загрузить DLL.

Заголовок выглядит так:

extern "C" __declspec(dllexport) BOOL Install();
extern "C" __declspec(dllexport) BOOL PPPConnect();

Это создает dll с немного запутанной таблицей экспорта (что означает foo = foo в поле имени?):

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, я получаю MissingMethodException - «Не удается найти точку входа« PPPConnect »в PInvoke DLL« 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, не распространяемым на устройство. D'ой!

Ответы [ 5 ]

8 голосов
/ 21 февраля 2009

Используете ли вы файл .def в своем проекте dll для экспорта этих функций? Если это так, удалите его и попробуйте снова. Это всего лишь предположение, потому что похоже, что ваши экспорты не такие, какими они должны быть, когда вы делаете extern "C" declspec (dllexports).

Я попробовал это с помощью простой C ++ dll, используя

extern "C" __declspec(dllexport) BOOL Install();
extern "C" __declspec(dllexport) BOOL PPPConnect();

и простое приложение на C #, использующее ваши объявления PInvoke , и оно работало нормально.

Когда я делал dumpbin / export на 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)

Обратите внимание, что экспортируемые имена в моем случае отличаются.

1 голос
/ 21 февраля 2009

Это может быть что-то такое же простое, как и PPPConnect, который может быть неверно истолкован ОС. Попробуйте реализовать как Install, так и PPPConnect как no-ops (просто сделайте так, чтобы они возвращали TRUE, ничего не делая) и посмотрите, не исчезнет ли ошибка. Если это так, попробуйте поменять местами порядок их экспорта (все еще в режиме no-ops) и посмотрите, связана ли проблема с упорядочением (маловероятно) или чем-то другим.

Вы также можете использовать графический инструмент depends, чтобы подтвердить, как выглядит таблица экспорта DLL, но я сомневаюсь, что проблема исходит от этих кварталов.

1 голос
/ 21 февраля 2009

Согласно вашему описанию Install и PPPConnect отличаются только именами. Я полагаю, вы просто используете старую версию .dll с вашим приложением C #. Определен один без PPPConnect.

Декларации выглядят правильно (насколько я могу судить без источников).

0 голосов
/ 27 марта 2009

используйте обходчик зависимостей и откройте свою DLL, чтобы проверить, какие методы доступны

0 голосов
/ 21 февраля 2009

Отличная информация, но, как вы упоминаете, здесь все в порядке. Попробуйте установить средства отладки для 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 делает что-то странное.

...