2

JNAを使用してdelphidllの関数を呼び出そうとしています。関数の定義は次のとおりです。

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が実際のテキストで埋められることを期待しています。

これはすべて、Java764ビットを搭載したWindows7で実行されています。DLLは32ビットDLLです。

更新と解決策:

コメントをありがとうDavidとRob。stdcall宣言を使用するようにdelphi定義を変更しました。関数を呼び出すと、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));
}
4

2 に答える 2

4

それがDLL関数の実際の宣言である場合、問題は呼び出し規約である可能性があります。Delphiのデフォルトの呼び出し規約はでregister、最初の2つの引数をEAXとEDXに格納しますが、デフォルトのCの呼び出し規約はcdecl、それらをスタックに格納します。Delphi宣言を次のように変更します。

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

exportディレクティブは(Delphi 2の時点では)実際には何も実行しないので、削除できます。これexportsは、DLLソースの他の場所にある句に含まれています。)

Java側も間違っています。Delphiコードの2番目のパラメータは、への参照ですPWideCharWStringByReferenceJNAにはタイプがありませんが、それが必要です。ただし、自分で実装する方法についてアドバイスすることはできません。

于 2012-06-04T16:28:43.133 に答える
1

stdcall呼び出し規約を使用する必要があり、文字列パラメーターが正しく宣言されていません(私は思います)。exportキーワードは使用されなくなり、省略できます。ライブラリコードの別の場所で、exportsキーワードを使用してエクスポートに名前を付けます。

Delphi関数は次のようになります。

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

PointerByReferenceについてはよくわかりません。それがvoid**と同等である場合、なぜそれをTHandleにマッピングするのですか?

于 2012-06-04T16:27:52.963 に答える