2016-11-01 20 views
0

나는 (Win32 API에 대한 호출 : 데이터를 저장하기 위해 WM_COPYDATA와 COPYDATASTRUCT를 가진 SendMessage를) 작동시키기 위해 많은 노력을 기울 였고, 지금 나의 윈도우 7 컴퓨터에서 작동하므로, 나의 매핑이 좋은지 궁금하다. 내 솔루션의 부작용이 없다면? , 중요한 것은 내가 인터넷에서 발견 한 모든 것을 비교하여이 코드JNA : COPYDATASTRUCT에 대한 올바른 매핑은 무엇입니까?

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입니다 :

/** 
    * 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" }); 
    } 
} 

그리고이 개 예제와 함께 호출 코드 : 여기

내 코드입니다 속성 cbData 유형이 long입니다. int로 설정하면 작동하지 않습니다 (데이터가 레거시 C 응용 프로그램의 WndProc에서 올바르게 수신되지 않음). DWORD를 긴 java 유형에 매핑하는 것이 맞습니까? NativeLong으로 더 좋을까요?

주목해야 할 또 다른 것은 모든 인스턴스화 된 구조체 (myStruct 및 myDataStruct)에 대한 Structure.write()를 명시 적으로 호출 한 것입니다. SendMessage API를 호출하기 전에 빈 메모리가 필요하지 않습니다. 정상이라고 생각하십니까? 아니면 jna SendMessage 호출하기 전에 자동으로 호출해야합니까?

미리 감사드립니다.

+0

JNA는 'DWORD'및 기타 창 유형에 대한 정의를 제공합니다. 네이티브'long '타입의 사용은 JNA의'NativeLong' 타입으로 표현되어야합니다. 'Structure.write()'는 구조체 인수를 가진 네이티브 함수 호출 전에 JNA에 의해 자동으로 호출됩니다. – technomage

+0

@technomage, 필자는 또 다른 테스트를했다. 올바른 동작을 위해 반드시 필요한 것은 아니다. 나는'Structure.toString (true)'에 대한 호출과 함께 디버깅을 위해 그것을 추가했다. DWORD 형식에 대해 사용하는 경우 메시지가 C라는 프로그램에 도착하지 않습니다. – cnico7

+0

다음은 정보를위한 것입니다 (Hello 문자열 테스트를위한) 메모리 덤프입니다 : DWORD가있는 메모리 덤프 cbData는 : 는 [0a000000] [0e000000] [00c2d058] [00000000] 메모리 cbData 긴로 덤프 : [0a000000] [00000000] [0e000000] [00000000] [306eda58] [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 비트라면 작동한다. 그리고 긴 타입의 dwData는 64 비트 JVM에서만 작동하지만 32 비트 JVM에서는 작동하지 않는다는 것을 확인합니다. 따라서 ULONG_PTR 유형은 JNA를 사용하여 메시지를 보내는 32 또는 64 비트 JVM에 따라 실제 크기가 다릅니다. 고맙습니다. – cnico7

+0

기술적으로 'ULONG_PTR'은 포인터를 맞추기에 충분히 큰 부호없는 long을 의미하기 때문에 32 비트와 64 비트에서 다르게 정의된다는 의미가 있습니다. 타입의 JNA 정의는 그 사실을 반영하여, 얼마나 큰지를 결정하기 위해'Pointer.SIZE'를 사용합니다. – technomage