Отображение функций delphi/pascal dll в дескрипторе и строке jna

Я пытаюсь вызвать функцию в DLL Delphi с использованием JNA. определение функции:

function myFuncGetName (aHandle : THandle; var aBuf : pwideChar ): integer; export;

мое отображение JNA выглядит так:

int myFuncGetName(PointerByReference aHandle, WString aBuf);

возвращаемое значение должно быть 0 для успеха и -1 для неудачи, и я всегда получаю -1.

Я запустил WinDbg и подключился к процессу, и он ломается на myFuncGetName.

057cb384 eb11            jmp     myDLL!myFuncGetName+0x87 (057cb397)
057cb386 b8dcb37c05      mov     eax,offset myDLL!myFuncGetName+0xcc (057cb3dc)
057cb38b 8b55f8          mov     edx,dword ptr [ebp-8]
057cb38e 8902            mov     dword ptr [edx],eax  ds:002b:00000000=???????? <-- ### breaks here ###
057cb390 c745f4ffffffff  mov     dword ptr [ebp-0Ch],0FFFFFFFFh

Я не мастер сборки, так что поправьте меня, где я не прав. Я думаю, что это перемещение адреса (аргумента функции) из местоположения ebp-8 в регистр edx. ebp-8 указывает на значение 0, поэтому edx равен 0. он перемещает eax по адресу, указанному edx. Это не должно перемещать что-либо в 0, так что все ломается?

Почему мои аргументы неправильно передаются в функцию? Я получаю aHandle из той же DLL из предыдущего вызова и устанавливаю aBuf как WString aBuf = new WString ("placeholderstring"); Я ожидаю, что aBuf будет заполнен реальным текстом после возврата функции.

Это все работает на Windows 7 с Java 7 64bit. DLL является 32-битной DLL.

ОБНОВЛЕНИЕ И РЕШЕНИЕ:

Спасибо Дэвид и Роб за ваши комментарии. Я изменил определение delphi для использования объявления stdcall. Вызов функции теперь возвращает 0, что и должно быть. Чтобы получить значение pwideChar, я сделал следующее:

int charcount= "placeholder".length();
PointerByReference aBuf = new PointerByReference(new Memory(charcount*4));
int returnvalue = myFuncGetName(aHandle, aBuf);
if(returnvalue == 0) {
    System.out.println(aBuf.getValue().getString(0, true));
}

2 ответа

Решение

Если это реальное объявление функции DLL, то проблема может заключаться в соглашении о вызовах. Соглашение о вызовах по умолчанию в Delphi: register, который хранит первые два аргумента в EAX и EDX, но соглашение о вызовах C по умолчанию cdecl, который хранит их в стеке. Измените объявление Delphi на это:

function myFuncGetName(aHandle: THandle; var aBuf: PWideChar): Integer; stdcall;

(The export директива на самом деле больше ничего не делает (я думаю, что в Delphi 2), так что вы можете удалить ее. Это было включено в exports пункт, который вы должны найти в другом месте в источнике DLL.)

Сторона Java тоже не права. Второй параметр в коде Delphi является ссылкой на PWideChar, Не вижу WStringByReference введите JNA, но это то, что вам нужно. Но я не могу дать совет, как это сделать самостоятельно.

Вам нужно будет использовать соглашение о вызовах stdcall, и строковый параметр объявлен неправильно (я думаю). Ключевое слово export больше не используется и может быть опущено. Вы называете свои экспорты ключевым словом export, где-то еще в коде вашей библиотеки.

Ваша функция Delphi должна быть такой.

function myFuncGetName(aHandle: THandle; aBuf: pwideChar): integer; stdcall;

Я не уверен насчет PointerByReference. Если это эквивалентно void**, почему вы отображаете его в THandle?

Другие вопросы по тегам