函数映射jna句柄和字符串中的delphi / pascal dll

时间:2012-06-04 16:02:16

标签: java delphi dll parameters jna

我正在尝试使用JNA在delphi dll中调用函数。功能定义是:

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所以它都会破坏?

为什么我的参数没有正确传递给函数? 我从之前的调用中得到了来自同一个DLL的aHandle,我将aBuf设置为 WString aBuf = new WString(“placeholderstring”); 我希望在函数返回后,aBuf会被填充真实文本。

这都是在带有java 7 64bit的Windows 7上运行的。 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 个答案:

答案 0 :(得分:4)

如果这是DLL函数的真实声明,则问题可能是调用约定。 Delphi中的默认调用约定是register,它将前两个参数存储在EAX和EDX中,但默认的C调用约定是cdecl,它将它们存储在堆栈中。将Delphi声明更改为:

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

export指令实际上不再执行任何操作(我认为是Delphi 2),所以你可以删除它。它被exports子句所包含,你应该找到它DLL源代码中的其他地方。)

Java方面也是错误的。 Delphi代码中的第二个参数是{em>引用到PWideChar。我在JNA中看不到WStringByReference类型,但这就是你需要的。但是,我无法就如何自己实施它提出任何建议。

答案 1 :(得分:1)

你需要使用stdcall调用约定,并且字符串参数声明不正确(我认为)。不再使用export关键字,可以省略。您可以使用exports关键字在库代码中的其他位置命名导出。

您的Delphi功能应该是这样的。

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

我不确定PointerByReference。如果这相当于void **,为什么要将它映射到THandle?