IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> Qt MinGW编译CyAPI源码生成静态库,支持32位,64位编译 -> 正文阅读

[开发工具]Qt MinGW编译CyAPI源码生成静态库,支持32位,64位编译

一、前言

最近需要做Windows平台 + Qt MinGW编译器做上位机与USB通信,USB芯片使用Cypress芯片。试了libusb,只能在Linux平台下使用,Windows平台用不了。所以只能使用Cypress提供的官方库CyAPI,但是Cypress官网只提供了vs版本的源码编译,在Qt下使用需要重新编译,苦于没有找到现成的资源只能自己编译,搞了一天,不过真心不难,只是没有注意细节。在此记录一下编译过程,也分享给需要的小伙伴。

不想自己编译的同学可以直接跳到下载地址:
静态库工程下载地址

二、 准备

需要准备好CyAPI源码,我是在官网下载的
官网下载地址
到这个链接下找到以下文件下载即可。
在这里插入图片描述
官网下载需要注册登录,觉得麻烦的小伙伴可以到这个地址下载(我自己上传的,也是想赚点积分。。):
CyAPI源码下载地址

三、 编译

  1. 使用Qt Creator建立一个新工程,选择C++库,我选择了静态库,动态库应该也可以,但是我没试,有兴趣的同学可以试一下。
    在这里插入图片描述
    在这里插入图片描述

  2. 建好工程以后直接把下载好的源码导入到工程中来,然后把不需要的文件移除掉,以下是我建好的工程目录:
    在这里插入图片描述

  3. 然后在pro文件中加入以下内容:

# 引入包含目录
INCLUDEPATH += $$PWD/inc 

#添加依赖库
LIBS+=-L$$PWD -lsetupapi

#配置文件输出路径
greaterThan(QT_MAJOR_VERSION,4){
        TARGET_ARCH=$${QT_ARCH}
}else{
        TARGET_ARCH=$${QMAKE_HOST.arch}
}
contains(TARGET_ARCH, x86_64){
    CONFIG(debug,debug|release){
        MOC_DIR = build/x64/tmp_debug/moc
        RCC_DIR = build/x64/tmp_debug/rcc
        OBJECTS_DIR = build/x64/tmp_debug/obj
        DESTDIR = build/x64/bin/debug/
    }else{
        MOC_DIR = build/x64/tmp_release/moc
        RCC_DIR = build/x64/tmp_release/rcc
        OBJECTS_DIR = build/x64/tmp_release/obj
        DESTDIR = build/x64/bin/release/
    }
}else{
    CONFIG(debug,debug|release){
        MOC_DIR = build/x86/tmp_debug/moc
        RCC_DIR = build/x86/tmp_debug/rcc
        OBJECTS_DIR = build/x86/tmp_debug/obj
        DESTDIR = build/x86/bin/debug/
    }else{
        MOC_DIR = build/x86/tmp_release/moc
        RCC_DIR = build/x86/tmp_release/rcc
        OBJECTS_DIR = build/x86/tmp_release/obj
        DESTDIR = build/x86/bin/release/
    }
}
  1. 在Qt安装目录下找到libsetupapi.a库,拷贝到工程目录。我的路径在以下位置。
    编译库的时候我只用了64位的setupapi库,实际测试程序时才需要根据实际情况替换32位或者64位的setupapi库。
// 32位
D:\Qt\Qt5.12.10\Tools\mingw730_32\i686-w64-mingw32\lib\libsetupapi.a

// 64位
D:\Qt\Qt5.12.10\Tools\mingw730_64\x86_64-w64-mingw32\lib\libsetupapi.a
  1. 以上几步完成后就可以开始编译了。
    5.1 头文件中会显示很多错误,类似下图,不用理会,不会影响编译结果。
    在这里插入图片描述
    cpp文件中也会报错,以下错误不用理会
    在这里插入图片描述
    5.2 需要修改的地方
MessageBox(NULL,"Please correct firmware descriptor table","Wrong Device Configuration",NULL);
改为:
MessageBoxA(NULL,"Please correct firmware descriptor table","Wrong Device Configuration",NULL);

就是把MessageBox改成MessageBoxA,因为默认调用MessageBoxW,参数不匹配,所以会报错。报错的地方改一下就可以。这个错误应该是有两处,都在Open函数中。

5.3 然后找到以下函数整体替换,其实也是CHAR和WCHAR参数不匹配的问题:

bool CCyUSBDevice::CreateHandle(UCHAR dev){

    Devices = DeviceCount();

    if (!Devices) return false;

    if (dev > (Devices - 1)) return false; //dev = Devices-1;

    SP_DEVINFO_DATA devInfoData;
    SP_DEVICE_INTERFACE_DATA  devInterfaceData;
    PSP_INTERFACE_DEVICE_DETAIL_DATA_A functionClassDeviceData; // 此处修改
    SP_INTERFACE_DEVICE_DETAIL_DATA_A tmpInterfaceDeviceDetailData; // 此处修改

    ULONG requiredLength = 0;
    int deviceNumber = dev;

    HANDLE hFile;

    //Open a handle to the plug and play dev node.
    //SetupDiGetClassDevs() returns a device information set that contains info on all
    // installed devices of a specified class which are present.
    HDEVINFO hwDeviceInfo = SetupDiGetClassDevsA ( (LPGUID) &DrvGuid,
        NULL,
        NULL,
        DIGCF_PRESENT|DIGCF_INTERFACEDEVICE); // 此处修改

    if (hwDeviceInfo != INVALID_HANDLE_VALUE) {

        //SetupDiEnumDeviceInterfaces() returns information about device interfaces
        // exposed by one or more devices. Each call returns information about one interface.
        //The routine can be called repeatedly to get information about several interfaces
        // exposed by one or more devices.

        devInterfaceData.cbSize = sizeof(devInterfaceData);

        if (SetupDiEnumDeviceInterfaces ( hwDeviceInfo, 0, (LPGUID) &DrvGuid,
            deviceNumber, &devInterfaceData)) {
                //Allocate a function class device data structure to receive the goods about this
                // particular device.
                SetupDiGetInterfaceDeviceDetailA ( hwDeviceInfo, &devInterfaceData, NULL, 0,
                    &requiredLength, NULL); // 此处修改

                ULONG predictedLength = requiredLength;

                functionClassDeviceData = (PSP_INTERFACE_DEVICE_DETAIL_DATA_A) malloc (predictedLength); // 此处修改
                functionClassDeviceData->cbSize =  sizeof (SP_INTERFACE_DEVICE_DETAIL_DATA_A);
                devInfoData.cbSize = sizeof(devInfoData); // 此处修改
                //Retrieve the information from Plug and Play */
                // 此处修改
                if (SetupDiGetInterfaceDeviceDetailA (hwDeviceInfo,
                    &devInterfaceData,
                    functionClassDeviceData,
                    predictedLength,
                    &requiredLength,
                    &devInfoData)) {

                        /* NOTE : x64 packing issue ,requiredLength return 5byte size of the (SP_INTERFACE_DEVICE_DETAIL_DATA) and functionClassDeviceData needed sizeof functionClassDeviceData 8byte */
                        int pathLen = requiredLength - (sizeof (tmpInterfaceDeviceDetailData.cbSize)+sizeof (tmpInterfaceDeviceDetailData.DevicePath));
                        //int pathLen = requiredLength - functionClassDeviceData->cbSize;

                        memcpy (DevPath, functionClassDeviceData->DevicePath, pathLen);
                        DevPath[pathLen] = 0;

						// 此处修改
                        hFile = CreateFileA (DevPath,
                            GENERIC_WRITE | GENERIC_READ,
                            FILE_SHARE_WRITE | FILE_SHARE_READ,
                            NULL,
                            OPEN_EXISTING,
                            FILE_FLAG_OVERLAPPED,
                            NULL);

                        DWORD errCode =  GetLastError();
                        free(functionClassDeviceData);
                        SetupDiDestroyDeviceInfoList(hwDeviceInfo);

                        if (hFile == INVALID_HANDLE_VALUE)
                        {
                            LastError = GetLastError();
                            return false;
                        }
                        // hDevice, DevNum, USBDeviceDescriptor, and Configs are data members
                        hDevice = hFile;

                        return true;
                }

        }

        SetupDiDestroyDeviceInfoList(hwDeviceInfo);

    }

    // Got here by failing at some point

    hDevice = INVALID_HANDLE_VALUE;
    DevNum = 0;
    return false;

}

5.4 DeviceCount函数修改一行或者直接替换:

UCHAR  CCyUSBDevice::DeviceCount(void){

    //SP_DEVINFO_DATA devInfoData;
    SP_DEVICE_INTERFACE_DATA  devInterfaceData;

    //Open a handle to the plug and play dev node.
    //SetupDiGetClassDevs() returns a device information set that contains info on all
    // installed devices of a specified class which are present.
    // 此函数修改
    HDEVINFO hwDeviceInfo = SetupDiGetClassDevsA ( (LPGUID) &DrvGuid,
        NULL,
        NULL,
        DIGCF_PRESENT|DIGCF_INTERFACEDEVICE); 

    Devices = 0;

    if (hwDeviceInfo != INVALID_HANDLE_VALUE) {

        //SetupDiEnumDeviceInterfaces() returns information about device interfaces
        // exposed by one or more devices. Each call returns information about one interface.
        //The routine can be called repeatedly to get information about several interfaces
        // exposed by one or more devices.

        devInterfaceData.cbSize = sizeof(devInterfaceData);

        // Count the number of devices
        int i=0;
        Devices = 0;
        bool bDone = false;

        while (!bDone) {
            BOOL bRetVal = SetupDiEnumDeviceInterfaces (hwDeviceInfo, 0, (LPGUID) &DrvGuid,
                i, &devInterfaceData);

            if (bRetVal)
                Devices++;
            else {
                DWORD dwLastError = GetLastError();
                if (dwLastError == ERROR_NO_MORE_ITEMS) bDone = TRUE;
            }

            i++;
        }

        SetupDiDestroyDeviceInfoList(hwDeviceInfo);
    }

    return Devices;
}

到此就修改完毕可以成功编译了,编译完成后到配置好的路径下找到编译好的库文件就可以使用了。

四、下载

我的工程上传到此,需要的可以下载。
静态库工程下载地址

五、测试

篇幅太长,下一篇写测试过程

  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2021-11-24 08:09:39  更:2021-11-24 08:11:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 18:40:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码