JNA:COPYDATASTRUCT 的正确映射?
JNA : Correct mapping for COPYDATASTRUCT?
我费了很大的劲才让它工作(调用 win32 API : SendMessage with WM_COPYDATA 和 COPYDATASTRUCT 来保存数据)并且它在我的 windows 上工作现在有 7 台电脑,我想知道我的映射是否正确,我的解决方案是否没有副作用?
这是我的代码:
/**
* 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 映射到 long java 类型是否正确?使用 NativeLong 会更好吗?
另一件需要注意的事情是对所有实例化结构(myStruct 和 myDataStruct)显式调用 Structure.write()。为了在调用 SendMessage api 之前没有空内存是必要的。
你觉得正常吗?或者 jna 应该在调用 SendMessage 之前自动调用它?
提前致谢。
本机代码:
typedef struct tagCOPYDATASTRUCT {
ULONG_PTR dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
映射到此 JNA 结构定义:
public class COPYDATASTRUCT extends Structure {
ULONG_PTR dwData;
DWORD cbData; // or use "int"
Pointer lpData;
}
第一个和最后一个字段的大小将不同(并且结构将具有不同的 alignment/padding),具体取决于您是 运行 32 位还是 64 位。
我费了很大的劲才让它工作(调用 win32 API : SendMessage with WM_COPYDATA 和 COPYDATASTRUCT 来保存数据)并且它在我的 windows 上工作现在有 7 台电脑,我想知道我的映射是否正确,我的解决方案是否没有副作用?
这是我的代码:
/**
* 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 映射到 long java 类型是否正确?使用 NativeLong 会更好吗?
另一件需要注意的事情是对所有实例化结构(myStruct 和 myDataStruct)显式调用 Structure.write()。为了在调用 SendMessage api 之前没有空内存是必要的。 你觉得正常吗?或者 jna 应该在调用 SendMessage 之前自动调用它?
提前致谢。
本机代码:
typedef struct tagCOPYDATASTRUCT {
ULONG_PTR dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
映射到此 JNA 结构定义:
public class COPYDATASTRUCT extends Structure {
ULONG_PTR dwData;
DWORD cbData; // or use "int"
Pointer lpData;
}
第一个和最后一个字段的大小将不同(并且结构将具有不同的 alignment/padding),具体取决于您是 运行 32 位还是 64 位。