Я изо всех сил пытался заставить его работать (вызов win32 API: SendMessage с WM_COPYDATA и COPYDATASTRUCT для хранения данных), и, поскольку он работает на моем компьютере с 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, это не сработает (данные неверно получены в WndProc унаследованного приложения C). Правильно ли отображать DWORD на длинный тип java? Было бы лучше с NativeLong?
Другое, что нужно отметить, это явный вызов Structure.write() для всех созданных объектов (myStruct и myDataStruct). Это необходимо, чтобы не иметь пустую память перед вызовом SendMessage api. Считаете ли вы, что это нормально? Или jna должен вызывать это автоматически перед вызовом SendMessage?
Заранее спасибо.
JNA предоставляет определения для 'DWORD' и других типов окон. Любое использование собственного типа 'long' должно быть представлено типом' NativeLong' JNA. 'Structure.write()' вызывается JNA автоматически перед вызовом любой функции с аргументами структуры. – technomage
@technomage, для записи я сделал еще один тест: это не обязательно для правильного поведения. Я добавил его для отладки с вызовом 'Structure.toString (true)'. Для типа DWORD, если я его использую, сообщение не поступает в C-называемую программу ... – cnico7
Вот для информации, дампы памяти в трассировке (для теста со строкой Hello): дамп памяти с DWORD для cbData: [0a000000] [0e000000] [00c2d058] [00000000] дамп памяти с длиной для cbData: [0a000000] [00000000] [0e000000] [00000000] [306eda58] [00000000 ] – cnico7