2016-11-01 17 views
0

私はそれが(Win32 APIへの呼び出し:データを保持するために、WM_COPYDATAとCOPYDATASTRUCTでSendMessage)を働かせるために多くの苦労しています、そして、今私のWindows 7コンピュータで動作するように、私のソリューションの副作用がない場合は?ここでJNA:COPYDATASTRUCTの正しいマッピングですか?

は私のコードです:

/** 
    * For usage with WM_COPYDATA 
    * cf : https://msdn.microsoft.com/en-us/library/windows/desktop/ms649010(v=vs.85).aspx 
    */ 
    long SendMessage(HWND hWnd, int msg, WPARAM wParam, COPYDATASTRUCT.ByReference lParam); 

    int WM_COPYDATA = 0x004A; 


//cf : https://msdn.microsoft.com/en-us/library/windows/desktop/ms649010(v=vs.85).aspx 
class COPYDATASTRUCT extends Structure { 

    public static class ByReference extends COPYDATASTRUCT implements Structure.ByReference { 
    } 

    public COPYDATASTRUCT() { 
     super(); 
    } 

    public int dwData; 
    public long cbData; 
    public Pointer lpData; 

    protected List<String> getFieldOrder() { 
     return Arrays.asList(new String[] { "dwData", "cbData", "lpData" }); 
    } 
} 

そして2例と呼び出しコード:

User32Extension.COPYDATASTRUCT.ByReference dataStruct = new User32Extension.COPYDATASTRUCT.ByReference(); 
     String message = "Hello ! :-) !"; 
     Memory m = new Memory(message.length() + 1); 
     m.setString(0, message); 
     dataStruct.dwData = 10; 
     dataStruct.cbData = message.length() + 1; 
     dataStruct.lpData = m; 
     dataStruct.write(); // writes to native memory the structure. 
     result = user32.SendMessage(hwndTarget, // target hwnd. 
       User32Extension.WM_COPYDATA, // copy data message. 
       wparam, // current hwnd 
       dataStruct // data by reference here 
     ); 

     User32Extension.COPYDATASTRUCT.ByReference myDataStruct = new User32Extension.COPYDATASTRUCT.ByReference(); 
     User32Extension.TEST_STRUCT myStruct = new User32Extension.TEST_STRUCT(); 
     //simple C structure here with 4 fields of C types int, char, char and long. 
     myStruct.iNumber = 677; 
     myStruct.cCode = 'E'; 
     myStruct.cCode2 = 'T'; 
     myStruct.lLong1 = new NativeLong(123456789L); 
     myStruct.write(); 
     LOGGER.trace("myStruct (size=" + myStruct.size() + ")=" + myStruct.toString(true)); 

     myDataStruct.dwData = 11; 
     myDataStruct.cbData = myStruct.size(); 
     myDataStruct.lpData = myStruct.getPointer(); 
     myDataStruct.write(); // writes to native memory the structure. 
     result = user32.SendMessage(hwndTarget, // target hwnd. 
       User32Extension.WM_COPYDATA, // copy data message. 
       wparam, // current hwnd 
       myDataStruct // data 
     ); 

重要なのは、私がネット上で見つけたすべてのものに比べて、このコードで、そのCOPYDATASTRUCTです属性cbDataの型がlongです。 intに設定すると動作しません(レガシーCアプリケーションのWndProcでデータが正しく受信されません)。 DWORDを長いjava型にマップするのは正しいですか? NativeLongの方が良いでしょうか?

もう1つ注目すべきことは、すべてのインスタンス化された構造体(myStructおよびmyDataStruct)のStructure.write()を明示的に呼び出すことです。 SendMessage APIを呼び出す前に空のメモリを持たないことが必要です。 それは正常だと思いますか?またはSendMessageを呼び出す前にjnaが自動的に呼び出す必要がありますか?

ありがとうございます。

+0

JNAは、 'DWORD'と他のウィンドウタイプの定義を提供します。ネイティブの 'long'型の使用は、JNAの' NativeLong'型で表現されるべきです。 'Structure.write()'は構造体引数を持つネイティブ関数呼び出しの前にJNAによって自動的に呼び出されます。 – technomage

+0

@technomage、書き込みのために、別のテストを行った:正しい動作のために必要ではない。 'Structure.toString(true)'を呼び出すことでデバッグのために追加しました。 DWORDタイプの場合、私が使用すると、メッセージはプログラムと呼ばれるCに到着しません。 – cnico7

+0

ここでは、情報のために、トレースのメモリダンプ(Hello文字列を使ったテスト用): DWORDのメモリダンプ [0a000000] [00000000] [0e000000] [00000000] [306eda58] [00000000:CBDATA:CBDATAのために長いと [0a000000] [0e000000] [00c2d058] [00000000] メモリダンプ] – cnico7

答えて

0

このネイティブコード:このJNA構造定義へ

typedef struct tagCOPYDATASTRUCT { 
    ULONG_PTR dwData; 
    DWORD  cbData; 
    PVOID  lpData; 
} COPYDATASTRUCT, *PCOPYDATASTRUCT; 

マップ:

public class COPYDATASTRUCT extends Structure { 
    ULONG_PTR dwData; 
    DWORD  cbData; // or use "int" 
    Pointer lpData; 
} 

最初と最後のフィールドは、異なるサイズのものであろう(及び構造が異なる配向/パディングを有するであろう) 32ビットまたは64ビットのどちらを実行しているかによって異なります。

+0

最初は働いていませんでした(理由を見つけました)。これまでのところ、私の現在のテストでは、JVMが32または64ビットであれば動作します。 long型のdwDataは64ビットJVMでしか動作しますが、32ビットJVMでは動作しないことを確認します。そのため、ULONG_PTR型は、JNAを使用してメッセージを送信する32ビットまたは64ビットのJVMに応じて、実際にはサイズが異なります。ありがとうございました。 – cnico7

+0

私は、技術的には 'ULONG_PTR'はポインタに合う大きさの符号なしlongであると考えているので、それは32対64ビットで異なって定義されていることに意味があります。型のJNA定義はその事実を反映しており、Pointer.SIZEを使用してその大きさを判断します。 – technomage

関連する問題