У меня есть C++ DLL с открытой функцией API, использующей extern "C", и я использую эти функции в Python, используя функции-оболочки функций ctypes. По сути, я просто хочу сделать оболочку для доступа к API моей DLL.
Однако я заметил, что, хотя большинство моих функций работают правильно, функции, касающиеся зарегистрированного процесса обратного вызова и окна только для сообщений, использующие функции Windows API RegisterClassEx и CreateWindowEx, не работают.
Я использую 64-разрядную версию Python (3.6.8), поэтому мне было интересно, может ли быть несоответствие. Моя DLL 64-битная и работает в других средах. Есть ли причина, по которой Windows API не работает?
Результаты отладки:
Мой код достигает события WM_CREATE в процессе обратного вызова, но не достигает события WM_DEVICECHANGE. Опять же, этот код доступен в других средах, поэтому я пытаюсь выяснить, что отличается от Python.
WM_CREATE отправляется самим CreateWindowEx() перед выходом, поэтому он не зависит от активного цикла сообщений, в отличие от большинства других сообщений.
Вы зарегистрировали это сообщение в своем приложении?
@RemyLebeau Я создал функции-оболочки на C# и могу вызывать функции из сред C++ (например, Qt), в которых всегда достигается WM_DEVICECHANGE. Я пытаюсь придумать причину, по которой Python будет заблокирован. Я проверил RegisterDeviceNotification, который возвращает true, поэтому я в тупике, почему не приходят уведомления. Моя DLL 64-битная, а Python 64-битная. Я также попробовал 32-битную DLL в 32-битной версии Python, которая тоже не сработала. Другие функции работают, поэтому просто система событий не получает уведомления.






Windows только для сообщенийНЕ получают широковещательные сообщения:
A message-only window enables you to send and receive messages. It is not visible, has no z-order, cannot be enumerated, and does not receive broadcast messages. The window simply dispatches messages.
Вместо этого вы должны создать окно верхнего уровня и не вызывать showWindow.
Кроме того, не нужно вызывать CreateWindow/CreateWindowEx через DLL, попробуйте использовать WinAPI, импортировав модуль win32api, win32con, win32gui. Вот образец.
ОБНОВИТЬ:
Пример C++, который не может получить WM_DEVICECHANGE с окном только для сообщений.
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
MessageBox(NULL, "WM_CREATE", "Message", 0);
break;
case WM_DEVICECHANGE:
MessageBox(NULL, "WM_DEVICECHANGE", "Message", 0);
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int main()
{
static const char* class_name = "NAME_CLASS";
WNDCLASSEX wx = {};
HWND hwnd;
HINSTANCE hInstance = GetModuleHandleA(NULL);
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = WndProc; // function which will handle messages
wx.hInstance = hInstance;
wx.lpszClassName = class_name;
if (RegisterClassEx(&wx)) {
hwnd = CreateWindowEx(0, class_name, "Title", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
// hwnd = CreateWindowEx(0, class_name, "Title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
// Create a normal top-level window which can receive the broadcast messages.
}
HACCEL hAccelTable = LoadAccelerators(hInstance, class_name);
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
Обновлено:
Накачка сообщений необходима после создания окна.
Он работает и в других средах, в основе которых лежат C# и C++. Я получаю уведомления о событиях без каких-либо проблем, поэтому я не думаю, что ваш ответ применим. Это единственное, с чем я столкнулся, когда пробовал это на Python. Импорт других модулей противоречит цели создания оболочки для DLL.
Нет, это не так. Хотя я не знаю, как работает ваша среда (поскольку я не вижу кода), но я могу поделиться протестированным мной образцом C++, который не может получить сообщение WM_DEVICECHANGE с окном только для сообщений.
Также см. это, stackoverflow.com/questions/10168467/…
@DavidHeffernan Вы имеете в виду, что окна только для сообщений могут получать WM_DEVICECHANGE или транслировать сообщения в python или в DLL?
Вы можете зарегистрироваться, чтобы получать эти сообщения. Не спешите делать вывод, что спрашивающий ожидает приема трансляций. Также прочитайте вопрос, функциональность, связанная с зарегистрированным процессом обратного вызова.
Давайте продолжить обсуждение в чате.
Создание окна — это только одна десятая часть сражения. Остальные 90% запускают насос сообщений (см.
GetMessageи др.). Что бы доставитьWM_DEVICECHANGEи другие сообщения оконной процедуре. Для этого вам, вероятно, потребуется крутить нить.