以ZLG提供的智能Can卡dll(32bit)文件为例
一般情况下,在Windows平台上使用VS来编写的dll文件无法在Qt中使用中直接使用,需要在dll文件中进行一些特殊的声明。这里我们来介绍一下如何在Windows平台上使用Qt来调用致远电子生产的USB CAN卡dll库。
库函数文件总共有三个文件:ControlCAN.h、ControlCAN.lib、ControlCAN.dll。
1.首先我们创建好Qt项目以后需要打开*.pro文件,然后文件最后加入一个win32平台的dll声明:
win32: LIBS += -L$$PWD/./ -lControlCAN
2.第二部需要将唯一的一个头文件ControlCAN.h添加到项目中。
3.接下来我们需要在类mainwindow的头文件中加入一些新的定义,便于使用。这些函数是在“【使用手册】CAN测试软件与接口函数使用手册V3.11”中明确给出的,包括函数的参数等信息。
这里我们主要是使用typedef语句来重定义一些函数类型。为了便于讲解,这里我们以typedefDWORD(__stdcall VCI_ResetCAN)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);为例做进一步的解释:
Typedef语句的作用不做解释,我们来关注后边的部分。DWORD在最前面,后面为两对括号。
可以简写为
DWORD(函数名)(x,x,x)
很明显这个语句的作用就是使用VCI_ResetCAN来表示形参类型为(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd)的函数。实际上这个函数是CAN卡复位函数。
然后我们使用我们Typedef的VCI_ResetCAN来定义一个指针。这个指针指向了一个形参类型为(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd)。具体语句为:
VCI_ResetCAN *pResetCAN;
可能很多人会想,还有一个词没有解释。至少我觉得很多人会这么想,因为这个关键字很少用。我就来解释一下__stdcall的作用吧,也不过多的解释。毕竟深究出来又是一大堆。__stdcall是用来告诉编译器,这里的函数调用方式为标准调用。因为不同的编译器调用函数的时候,调用方式是不一样的,如果还想有深入的了解,就去看看编译原理吧。
4.现在我们需要使用Qt提供的QLibrary类来解析dll文件。这个dll文件在ZLG提供的库函数文件夹kerneldlls中。我们需要解析USBCAN.dll。
首先在添加头文件"QLibrary.h"到项目中,QLibrary的使用方法,请参考Qt官方文档,虽然是全英文的,但是很容易懂。然后装载USBCAN.dll文件。解析完成以后,解析函数返回一个函数指针。这里我们需要利用第三部中定义的指针。具体方式如下:
pResetCAN=(VCI_ResetCAN *)lib.resolve("VCI_ResetCAN");
pResetCAN是步骤3中定义的指针。(VCI_ResetCAN *)将函数返回的指针转换成特定形参的函数指针。lib.resolve("VCI_ResetCAN")是将USBCAN.dll中的函数VCI_ResetCAN解析出来。
好了,到这里我们已经将VCI_ResetCAN(DWORD DevType, DWORD DevIndex, DWORD CANIndex);函数从dll文件中调用出来。我们在使用的时候就可以使用
pResetCAN(DWORD DevType, DWORD DevIndex, DWORD CANIndex);
的形式进行使用。
下面我将部分代码贴出:
Mainwindow.cpp
QLibrary lib("USBCAN.dll");if(false==lib.load())QMessageBox::warning(this,"Warning","dll load ok");pOpenDevice = (VCI_OpenDevice *)lib.resolve("VCI_OpenDevice");pCloseDevice = (VCI_CloseDevice *)lib.resolve("VCI_CloseDevice");pInitCAN = (VCI_InitCAN *)lib.resolve("VCI_InitCAN");pStartCAN = (VCI_StartCAN *)lib.resolve("VCI_StartCAN");pTransmitCAN = (VCI_Transmit *)lib.resolve("VCI_Transmit");pReceive = (VCI_Receive *)lib.resolve("VCI_Receive");pGetReceiveNum = (VCI_GetReceiveNum *)lib.resolve("VCI_GetReceiveNum");pClearBuffer = (VCI_ClearBuffer *)lib.resolve("VCI_ClearBuffer");pReadErrInfoCAN = (VCI_ReadErrInfo*)lib.resolve("VCI_ReadErrInfo");pResetCAN=(VCI_ResetCAN *)lib.resolve("VCI_ResetCAN");pSetReference=(VCI_SetReference *)lib.resolve("VCI_SetReference");pReadBoardInfo=(VCI_ReadBoardInfo *)lib.resolve("VCI_ReadBoardInfo");pReadCANStatus=(VCI_ReadCANStatus *)lib.resolve("VCI_ReadCANStatus");
Mainwindow.h
typedefDWORD(__stdcall VCI_OpenDevice)(DWORD,DWORD,DWORD);typedefDWORD(__stdcall VCI_ResetCAN)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);typedefDWORD(__stdcall VCI_CloseDevice)(DWORD DeviceType,DWORD DeviceInd);typedefDWORD(__stdcall VCI_InitCAN)(DWORD DeviceType, DWORD DeviceInd, DWORD CANInd, PVCI_INIT_CONFIG pInitConfig);typedefDWORD(__stdcall VCI_StartCAN)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);typedefULONG(__stdcall VCI_Transmit)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_OBJ pSend,ULONG Len);typedefULONG(__stdcall VCI_Receive)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_OBJ pReceive,ULONG Len,INT WaitTime/*=-1*/);typedefULONG(__stdcall VCI_GetReceiveNum)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);typedefDWORD(__stdcall VCI_ClearBuffer)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);typedefDWORD(__stdcall VCI_ReadErrInfo)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_ERR_INFO pErrInfo);typedefDWORD(__stdcall VCI_ReadCANStatus)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_STATUS pCANStatus);typedefDWORD(__stdcall VCI_SetReference)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,DWORD RefType,PVOID pData);typedefDWORD(__stdcall VCI_ReadBoardInfo)(DWORD DeviceType,DWORD DeviceInd,PVCI_BOARD_INFO pInfo);VCI_OpenDevice *pOpenDevice;VCI_ResetCAN *pResetCAN;VCI_CloseDevice *pCloseDevice;VCI_InitCAN *pInitCAN;VCI_StartCAN *pStartCAN;VCI_Transmit *pTransmitCAN;VCI_Receive *pReceive;VCI_GetReceiveNum *pGetReceiveNum;VCI_ClearBuffer *pClearBuffer;VCI_ReadErrInfo *pReadErrInfoCAN;VCI_ReadCANStatus *pReadCANStatus;VCI_SetReference *pSetReference;VCI_ReadBoardInfo *pReadBoardInfo;
Test.pro
win32: LIBS += -L$$PWD/./ -lControlCAN