创建线程消息循环服务于动态连接库

因为动态连接库需要对DBT_DEVICEARRIVAL、DBT_DEVICEREMOVECOMPLETE等消息的处理,所以拿一个不太理想的usb-hid的dll来说明,不多说直接上代码


 1 // 下列 ifdef 块是创建使从 DLL 导出更简单的
 2 // 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 WIN32USB_EXPORTS
 3 // 符号编译的。在使用此 DLL 的
 4 // 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
 5 // WIN32USB_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
 6 // 符号视为是被导出的。
 7 #ifdef WIN32USB_EXPORTS
 8 #define WIN32USB_API __declspec(dllexport)
 9 #else
10 #define WIN32USB_API __declspec(dllimport)
11 #endif
12
13 #ifdef __cplusplus
14 extern "C"{
15 #endif
16
17     typedef void(*UsbHandler)();
18
19     WIN32USB_API void UsbInit(int vid, int pid);
20     WIN32USB_API void UsbNotify(UsbHandler arrival, UsbHandler removed);
21     WIN32USB_API int UsbWrite(unsigned char *dat);
22     WIN32USB_API BOOL UsbRead(unsigned char *dat);
23     WIN32USB_API int InputReportByteLength();
24     WIN32USB_API int OutputReportByteLength();
25     WIN32USB_API bool Connected();
26     WIN32USB_API void UsbFree();
27
28 #ifdef __cplusplus
29 }
30 #endif
  1 // Win32Usb.cpp : 定义 DLL 应用程序的导出函数。
  2 //
  3
  4 #include "stdafx.h"
  5 #include "Win32Usb.h"
  6 #include <Dbt.h>
  7
  8 #pragma comment(lib, "hid.lib")
  9 #pragma comment(lib, "setupapi.lib")
 10
 11 bool connected = false;
 12 int inputReportByteLength;
 13 int outputReportByteLength;
 14
 15 int usb_vid = 0;
 16 int usb_pid = 0;
 17
 18 HANDLE hUsbWriter = INVALID_HANDLE_VALUE;
 19 HANDLE hUsbReader = INVALID_HANDLE_VALUE;
 20
 21 // 消息循环线程ID
 22 DWORD msglooper_tid = 0;
 23 HANDLE msgl_handle = INVALID_HANDLE_VALUE;
 24 WNDCLASS wndClass = { 0 };
 25 HDEVNOTIFY hDevnotify = INVALID_HANDLE_VALUE;
 26
 27 UsbHandler UsbArrivalHandler;
 28 UsbHandler UsbRemovedHandler;
 29
 30 OVERLAPPED ovw = {0};
 31 OVERLAPPED ovr = {0};
 32
 33 bool UsbFind();
 34
 35 WIN32USB_API void UsbInit(int vid, int pid)
 36 {
 37     usb_vid = vid;
 38     usb_pid = pid;
 39
 40     UsbFind();
 41 }
 42
 43 bool UsbFind()
 44 {
 45     GUID guid;
 46     HidD_GetHidGuid(&guid);
 47     HDEVINFO hdevinfo = SetupDiGetClassDevs(&guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
 48
 49     SP_DEVICE_INTERFACE_DATA device_interface_data;
 50     ZeroMemory(&device_interface_data, sizeof(device_interface_data));
 51     device_interface_data.cbSize = sizeof(device_interface_data);
 52
 53     //SP_DEVINFO_DATA devinfo_data;
 54     //devinfo_data.cbSize = sizeof(devinfo_data);
 55     //devinfo_data.ClassGuid = guid;
 56
 57     int device_interface_index = 0;
 58     while (SetupDiEnumDeviceInterfaces(hdevinfo, NULL, &guid, device_interface_index, &device_interface_data))
 59     {
 60         //SP_DEVICE_INTERFACE_DETAIL_DATA device_interface_detail_data;
 61         //ZeroMemory(&device_interface_detail_data, sizeof(device_interface_detail_data));
 62         //device_interface_detail_data.cbSize = sizeof(device_interface_detail_data);
 63         DWORD requireSize;
 64         SetupDiGetDeviceInterfaceDetail(hdevinfo, &device_interface_data, NULL, 0, &requireSize, NULL);
 65
 66         PSP_DEVICE_INTERFACE_DETAIL_DATA psp_device_interface_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requireSize);
 67         psp_device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
 68         if (SetupDiGetDeviceInterfaceDetail(hdevinfo, &device_interface_data, psp_device_interface_detail_data, requireSize, &requireSize, NULL))
 69         {
 70             char * _devicePath = psp_device_interface_detail_data->DevicePath;
 71             free(psp_device_interface_detail_data);
 72
 73             HANDLE _hDevice = CreateFile(_devicePath,
 74                 GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
 75             if (_hDevice != INVALID_HANDLE_VALUE)
 76             {
 77                 HIDD_ATTRIBUTES hidd_attributes;
 78                 HidD_GetAttributes(_hDevice, &hidd_attributes);
 79                 if (hidd_attributes.VendorID == usb_vid && hidd_attributes.ProductID == usb_pid)
 80                 {
 81                     PHIDP_PREPARSED_DATA phidp_preparsed_data;
 82                     HidD_GetPreparsedData(_hDevice, &phidp_preparsed_data);
 83                     HIDP_CAPS hidp_caps;
 84                     HidP_GetCaps(phidp_preparsed_data, &hidp_caps);
 85                     inputReportByteLength = hidp_caps.InputReportByteLength;
 86                     outputReportByteLength = hidp_caps.OutputReportByteLength;
 87                     HidD_FreePreparsedData(phidp_preparsed_data);
 88
 89                     hUsbWriter = CreateFile(_devicePath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
 90                         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
 91                     hUsbReader = CreateFile(_devicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
 92                         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
 93
 94                     SetupDiDestroyDeviceInfoList(hdevinfo);
 95                     CloseHandle(_hDevice);
 96                     connected = true;
 97                     return true;
 98                 }
 99
100                 CloseHandle(_hDevice);
101             }
102         }
103
104         device_interface_index++;
105     }
106
107     SetupDiDestroyDeviceInfoList(hdevinfo);
108     return false;
109 }
110
111 WIN32USB_API BOOL UsbRead(unsigned char *dat)
112 {
113     if (connected && hUsbReader != INVALID_HANDLE_VALUE)
114     {
115         DWORD read_size;
116         BOOL rt = ReadFile(hUsbReader, dat, inputReportByteLength, &read_size, &ovr);
117         if (!rt)
118         {
119             if (GetLastError() == ERROR_IO_PENDING)
120             {
121                 // 此时是否需要对IO状态作处理看需求,处理与否不会影响IO
122                 //rt = WaitForSingleObject(hUsbReader, 50);
123                 //switch (rt)
124                 //{
125                 //case WAIT_OBJECT_0:
126                 //    cout << "指定的对象处于有信号状态" << endl;
127                 //    if (GetOverlappedResult(hUsbReader, &ovr, &read_size, FALSE))
128                 //        cout << "read " << read_size << " bytes" << endl;
129                 //    break;
130                 //case WAIT_TIMEOUT:
131                 //    cout << "等待超时" << endl;
132                 //    break;
133                 //case WAIT_FAILED:
134                 //    cout << "出现错误,CODE [" << GetLastError() << "]" << endl;
135                 //    break;
136                 //case WAIT_ABANDONED:
137                 //    cout << "当Handle为mutex时,如果拥有mutex的线程在结束时没有释放核心对象会引发此返回值" << endl;
138                 //    break;
139                 //}
140
141                 // 这里是神精病代码<网络上此类代码非常多>
142                 //WaitForSingleObjectEx(hUsbReader, INFINITE, TRUE);
143                 //rt = GetOverlappedResult(hUsbReader, &ovr, &factBytes, FALSE);
144                 //return rt;
145             }
146             else
147             {
148                 CancelIo(hUsbReader);
149                 return FALSE;
150             }
151         }
152         else return TRUE;
153     }
154
155     return FALSE;
156 }
157
158 WIN32USB_API int UsbWrite(unsigned char *dat)
159 {
160     if (connected && hUsbWriter != INVALID_HANDLE_VALUE)
161     {
162         DWORD write_size;
163         BOOL rt = WriteFile(hUsbWriter, dat, outputReportByteLength, &write_size, &ovw);
164         if (!rt)
165         {
166             if (GetLastError() == ERROR_IO_PENDING)
167             {
168                 // 此时是否需要对IO状态作处理看需求,处理与否不会影响IO
169                 //rt = WaitForSingleObject(hUsbWriter, 50);
170                 //switch (rt)
171                 //{
172                 //case WAIT_OBJECT_0:
173                 //    cout << "指定的对象处于有信号状态" << endl;
174                 //    if (GetOverlappedResult(hUsbWriter, &ovr, &write_size, FALSE))
175                 //        cout << "write " << write_size << " bytes" << endl;
176                 //    break;
177                 //case WAIT_TIMEOUT:
178                 //    cout << "等待超时" << endl;
179                 //    break;
180                 //case WAIT_FAILED:
181                 //    cout << "出现错误,CODE [" << GetLastError() << "]" << endl;
182                 //    break;
183                 //case WAIT_ABANDONED:
184                 //    cout << "当Handle为mutex时,如果拥有mutex的线程在结束时没有释放核心对象会引发此返回值" << endl;
185                 //    break;
186                 //}
187
188                 // 这里是神精病代码<网络上此类代码非常多>
189                 //WaitForSingleObjectEx(hUsbWriter, INFINITE, TRUE);
190                 //rt = GetOverlappedResult(hUsbWriter, &ovw, &write_size, FALSE);
191                 //if (!rt) return 0;
192             }
193             else
194             {
195                 CancelIo(hUsbWriter);
196                 return 0;
197             }
198         }
199         return write_size;
200     }
201
202     return 0;
203 }
204
205 WIN32USB_API int InputReportByteLength(){return inputReportByteLength;}
206 WIN32USB_API int OutputReportByteLength(){ return outputReportByteLength; }
207 WIN32USB_API bool Connected(){ return connected; }
208
209 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
210 {
211     if (msg == WM_DEVICECHANGE)
212     {
213         //MessageBox(NULL, TEXT("WM_DEVICECHANGE"), TEXT("WndProc"), MB_OK);
214         //return 0;
215         switch (wParam)
216         {
217         case DBT_DEVICEARRIVAL:
218             //printf("[wndproc]device arrival.");
219             if (!connected)
220             {
221                 if (UsbFind())
222                 {
223                     if (UsbArrivalHandler != NULL) UsbArrivalHandler();
224                 }
225             }
226             break;
227         case DBT_DEVICEREMOVECOMPLETE:
228             //printf("[wndproc]device remove.");
229             if (connected)
230             {
231                 if (!UsbFind())
232                 {
233                     connected = false;
234                     if (hUsbWriter != INVALID_HANDLE_VALUE)
235                     {
236                         CloseHandle(hUsbWriter);
237                         hUsbWriter = INVALID_HANDLE_VALUE;
238                     }
239                     if (hUsbReader != INVALID_HANDLE_VALUE)
240                     {
241                         CloseHandle(hUsbReader);
242                         hUsbReader = INVALID_HANDLE_VALUE;
243                     }
244
245                     if (UsbRemovedHandler != NULL) UsbRemovedHandler();
246                 }
247             }
248             break;
249         default:
250             break;
251         }
252     }
253
254     return DefWindowProc(hWnd, msg, wParam, lParam);
255 }
256
257 void MessageLooper()
258 {
259     GUID guid;
260     HINSTANCE hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(NULL));
261     wndClass.lpfnWndProc = &WndProc;
262     wndClass.lpszClassName = TEXT("Win32Usb");
263     wndClass.hInstance = hInstance;
264     if (RegisterClass(&wndClass))
265     {
266         // 注意HWND_MESSAGE的关键使用
267         HWND wnd = CreateWindowEx(0, wndClass.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInstance, NULL);
268         if (wnd != NULL)
269         {
270             HidD_GetHidGuid(&guid);
271             DEV_BROADCAST_DEVICEINTERFACE notificationFilter = { 0 };
272             notificationFilter.dbcc_size = sizeof(notificationFilter);
273             notificationFilter.dbcc_classguid = guid;
274             notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
275             hDevnotify = RegisterDeviceNotification(wnd, &notificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
276
277             if (hDevnotify != NULL)
278             {
279                 MSG msg;
280                 if (GetMessage(&msg, NULL, 0, 0) > 0)
281                 {
282                     TranslateMessage(&msg);
283                     DispatchMessage(&msg);
284                 }
285
286                 connected = false;
287                 if (hUsbWriter != INVALID_HANDLE_VALUE)
288                 {
289                     CloseHandle(hUsbWriter);
290                     hUsbWriter = INVALID_HANDLE_VALUE;
291                 }
292                 if (hUsbReader != INVALID_HANDLE_VALUE)
293                 {
294                     CloseHandle(hUsbReader);
295                     hUsbReader = INVALID_HANDLE_VALUE;
296                 }
297
298                 UnregisterDeviceNotification(hDevnotify);
299             }
300             DestroyWindow(wnd);
301             UnregisterClass(wndClass.lpszClassName, hInstance);
302         }
303     }
304 }
305
306 WIN32USB_API void UsbNotify(UsbHandler arrival, UsbHandler removed)
307 {
308     UsbArrivalHandler = arrival;
309     UsbRemovedHandler = removed;
310     // 创建线程消息循环
311     msgl_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MessageLooper, NULL, THREAD_PRIORITY_NORMAL, &msglooper_tid);
312 }
313
314 WIN32USB_API void UsbFree()
315 {
316     connected = false;
317     // 关闭仅提供消息循环HWND_MESSAGE标识窗口
318     PostThreadMessage(msglooper_tid, WM_CLOSE, 0, 0);
319     CloseHandle(msgl_handle);
320 }


涉及的一些内容:

  1. 线程中CreateWindowEx的调用
  2. 在CreateWindowEx中使用HWND_MESSAGE的作用
  3. PostThreadMessage与PostMessage使用上区别的地方
时间: 2024-10-14 14:46:28

创建线程消息循环服务于动态连接库的相关文章

Android应用程序线程消息循环模型分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6905587 我们知道,Android应用程序是通过消息来驱动的,即在应用程序的主线程(UI线程)中有一个消息循环,负责处理消息队列中的消息.我们也知 道,Android应用程序是支持多线程的,即可以创建子线程来执行一些计算型的任务,那么,这些子线程能不能像应用程序的主线程一样具有消息循环呢?这 些子线程又能不能往应用程序的主线程中发送消息呢?本

Android----Thread+Handler 线程 消息循环(转载)

近来找了一些关于android线程间通信的资料,整理学习了一下,并制作了一个简单的例子. andriod提供了 Handler 和 Looper 来满足线程间的通信.例如一个子线程从网络上下载了一副图片,当它下载完成后会发送消息给主线程,这个消息是通过绑定在主线程的Handler来传递的. 在Android,这里的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper,这个事android的新 概念.我们的主线程(UI线程)就是一个消息循环的线程.针对这种消息循

Thread+Handler 线程 消息循环(转载)

近来找了一些关于android线程间通信的资料,整理学习了一下,并制作了一个简单的例子. andriod提供了 Handler 和 Looper 来满足线程间的通信.例如一个子线程从网络上下载了一副图片,当它下载完成后会发送消息给主线程,这个消息是通过绑定在主线程的Handler来传递的. 在Android,这里的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper,这个事android的新 概念.我们的主线程(UI线程)就是一个消息循环的线程.针对这种消息循

窗口创建及消息循环

窗口创建 1. 自定义窗口类别           WNDCLASS 2. 注册窗口类               RegisterClass 3. 创建窗口                 CreateWindow/CreateWindowEx                 WM_CREATE 4. 显示窗口                 ShowWindow                                  WM_SIZE & WM_SHOWWINDOW 5. 更新窗口 

Qt动态连接库/静态连接库创建与使用,QLibrary动态加载库

版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt动态连接库/静态连接库创建与使用,QLibrary动态加载库     本文地址:http://techieliang.com/2017/12/680/ 文章目录 1. 动态连接库创建与使用  1.1. 项目创建  1.2. 调用-使用.h文件 2. 静态库创建及使用  2.1. 创建  2.2. 使用 3. QLibrary动态加载动态库  3.1. 介绍  3.2. 范例  3.3.

Linux 静态链接库和动态连接库

(0)文件夹 VMware 下安装Ubuntu的吐血经历 零基础学习Shell编程 Linux下的makefile的妙用 Linux调试神器 -- gdb 十分钟学会Python的基本类型 Linux 静态链接库和动态连接库 一:静态链接库的应用  三步走~~~ ##g++ -c StaticMath.cpp ##ar -crv libstaticmath.a StaticMath.o ##g++ -o run test_a.cpp -L. -lstaticmath #[@sjs_37_33 l

动态连接库 VS 静态连接库

一.静态库与动态库 通常情况下,对函数库的链接是放在编译时期(compile time)完成的.所有相关的对象文件(object file)与牵涉到的函数库(library)被链接合成一个可执行文件(executable file).程序在运行时,与函数库再无瓜葛,因为所有需要的函数已拷贝到自己门下.所以这些函数库被成为静态库(static libaray),通常文件名为"libxxx.a"的形式. 其实,我们也可以把对一些库函数的链接载入推迟到程序运行时期(runtime).这就是如

Linux下的动态连接库及其实现机制

Linux与Windows的动态连接库概念相似,但是实现机制不同.它引入了GOT表和PLT表的概念,综合使用了多种重定位项,实现了"浮动代码",达到了更好的共享性能.本文对这些技术逐一进行了详细讨论. 本文着重讨论x86体系结构,这是因为 (1)运行Linux的各种体系结构中,以x86最为普及: (2)该体系结构上的Windows操作系统广为人知,由此可以较容易的理解Linux的类似概念: 下表列出了Windows与Linux的近义词,文中将不加以区分: Windows Linux 动

linux(debian) 安装软件,缺少动态连接库.so

有以下几种提示: 1.缺少动态连接库.so-cannot open shared object file:No such file or directory 2.缺少动态连接库.so.0-cannot open shared object file:No such file or directory 3.缺少动态连接库.so.1-cannot open shared object file:No such file or directory 可以直接: # sudo ldconfig 再编译,如