QT如何使用vs导出的库函数

1. QT调用vs静态库

    vs编译出的静态库文件:xxx.lib xxx.h

    QT调用静态库会在编译阶段就加载具体函数实体,但因为QT默认使用MinGW编译器,而vs默认使用MSVC。两者编译方式不同,因此加载会不成功。

    解决办法:将QT编译器设置为vs相同的版本

2. QT调用vs动态库

    vs编译出动态库文件:xxx.dll xxx.lib xxx.h

    2.1. 显式调用

        显式调用只需要xxx.dll文件,但需要设置导出参数:

        {

        设置1. __ declspec(dllexport): 如果将一个函数作为导出函数被其它程序调用,需要在声明函数前加此标识符。同时vs也提供一种无需此标识符的方法,即使用xxx.def。只需将导出函数名写入xxx.def文件,并在工程属性中配置链接器-输入-模块定义文件,就可以在声明函数前去掉__ declspec(dllexport)标识了。两者的区别可另行研究。

        设置2. extern“C”:由于C++语法中函数存在重载,因为在编译C++时会将函数名进行修改,而加此标识符是告诉编译器按照C的语法进行编译次函数,即不修改函数名。

        设置3. __cdecl:默认C/C++调用方式是__cdecl,但是这种调用方式需要调用方对函数进行清栈处理, 尤其是调用方非C++程序时,会因为无法清栈而报错,可以设置调用方式为__stdcall,让API函数自己清栈。

        最终导出函数声明示例:extern "C" __declspec(dllexport) int __cdecl MyFuncAPI(int data);

        最终导出函数实现示例:int __cdecl MyFuncAPI(int data) { };

        }

        QLibrary lib("xxx.dll");

        if( ! lib.load()) error;

        typedef int (*MyFun)(int data);

        MyFun pMyFun = (MyFun)lib.resolve("MyFuncAPI");

        if(pMyFun) {

        int ret = pMyFun(a); };

    2.2. 隐式调用

        隐式调用需要xxx.lib xxx.h xxx.dll

        配置如同显式调用一样配置,在此不做累述。

        2.2.1. 打开QT工程中xxx.pro文件,在文件中右键(或在工程名右键)选择“添加库...”---外部库---选择xxx.lib文件,然后取消掉Linux和Mac平台,链接选择动态库等等。会默认在xxx.pro中添加编译所需配置。

        2.2.2. 在所需处包含头文件include "xxx.h"。在xxx.h中每一个导出的函数在函数名前加此标识符“__declspec(dllimport)”声明为导出函数,。

        最终示例为:extern "C" __declspec(dllimport) int __cdecl MyFuncAPI(int data);

        2.2.3. 将xxx.dll拷贝至QT工程生成xxx.exe相同目录下。

       此致在QT工程中调用动态库,如同调用普通函数。

3.QT打包发布

    3.1 QT动态链接

        QT默认是动态链接QT内的各种库,如需将应用程序发布则需要在exe同级目录下将需要的库都包含进去,其中包含:

        D:\Qt\(QT版本)\(编译器目录)\bin\Qt5Core.dll 、Qt5Gui.dll、Qt5Widgets.dll、libgcc_s_dw2-1.dll、libstdc++-6.dll、libwinpthread-1.dll等。

        D:\Qt\(QT版本)\(编译器目录)\plugins\platforms 下所有文件,将platforms整个文件夹包含文件夹本身拷贝至exe同级目录。

        拷贝原则:一个一个去拷贝难免会漏掉某个文件,导致运行异常的情况,建议使用qt自带工具进行拷贝。

        步骤1:将release里的应用程序hello.exe拷贝至helloqml文件夹下。

        步骤2:打开qt自带工具Qt 5.14.1 (MSVC 2017 32-bit) (一个cmd命令行界面)跳转至helloqml文件夹下,

                        具体命令:cd /d "D:\helloqml"

        步骤3:输入以下命令:windeployqt hello.exe --qmldir D:\Qt\5.14.1\msvc2017\qml 

        至此所有hello.exe所依赖的文件全部都被拷贝至helloqml文件夹下了。

    3.2 QT静态链接

        QT要实现静态编译,必须所用的QT库也是静态编译的(实际发现坑比较多)。具体步骤可参考:

        3.2.1. 下载编译所需要的工具:

            a.qt源码(http://download.qt.io/archive/qt/5.14/5.14.1/single/),Windows/Linux 按照自己所需平台下载

            b. 编译工具(MinGW/MSVC), 同样按照自己所需下载安装。

            c. Per(http://strawberryperl.com/) 32bit/64bit 按照自己所需平台下载。

            d. Python(https://www.python.org/downloads/windows/), 32bit/64bit 按照所需下载。

            e. Ruby(https://rubyinstaller.org/downloads/), 32bit/64bit 按照所需下载。

            PS:安装工具时,尽量都把将工具的名称添加到环境变量中去选项勾选上,否则需自己添加环境变量,安装完重启机器使环境变量生效,最后在命令行输入工具名称,查看是否都正常可用。

        3.2.2. 修改配置文件(以MSVC2017_32bit为例)

            修改QT源码里的qt-src-5.14\qtbase\mkspecs\common\msvc-desktop.conf文件,将MD和MDd修改成MT和MTd

        3.2.3. 打开编译器

            a. 管理员权限打开"x86 Native Tools Command Prompt for VS 2017"

            b. cd /d qt-everywhere-src-5.14.1\qt-everywhere-src-5.14.1

            c. configure.bat -static -static-runtime -prefix "E:\qt" -confirm-license -opensource  -debug-and-release -platform win32-msvc  -nomake examples -nomake tests  -plugin-sql-sqlite -plugin-sql-odbc -qt-zlib -qt-libpng -qt-libjpeg -opengl desktop -mp

            d. nmake(大约3-4个小时)

            e. nmake install

        3.2.4. 将编译好的Qt添加到Qt Creator

            a. 先添加Kits-Qt Version, 将E:\qt\bin\qmake.exe 添加至Qt Version

            b. 再添加Kits-Kit, 编译器选择你编译Qt所用的编译器,C和C++可以选择同一个。Qt version 选择刚才自己创建的那个。

        3.2.5. 在QtCreator中选择刚才创建的那个kit对程序进行编译,这样编译用到的库就是静态链接了。

    4. 静态链接MFC静态库 xxx.lib遇到的问题记录

        4.1. 在qt项目中使用.pro文件添加windows静态库链接后,编译报错:uafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) 已经在 LIBCMT.lib(new.obj) 中定义

            解决办法:通过在网上查询大概意思是CRT库对new delete等使用弱外部链接,MFC库中也包含了new delete 等函数,所以在使用的时候需要先链接MFC的库,再链接CRT的库。于是要先在忽略特定库中添加uafxcwd.lib libcmtd.lib(Debug版本),再在引用库中加回uafxcwd.lib libcmtd.lib(Debug版本),具体在.pro文件中添加如下代码:

win32:CONFIG(release, debug|release): {
    QMAKE_LFLAGS_RELEASE += /NODEFAULTLIB:uafxcw.lib /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:msvcrt.lib
    QMAKE_LIBS += uafxcw.lib libcmt.lib
}
else:win32:CONFIG(debug, debug|release): {
    QMAKE_LFLAGS_DEBUG += /NODEFAULTLIB:uafxcwd.lib /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrtd.lib
    QMAKE_LIBS += uafxcwd.lib libcmtd.lib
}

你可能感兴趣的:(visual,studio,qt5)