Qt动态链接库
一、生成可执行文件流程
处理流程 | 文件后缀 | 语言 | 操作指令 |
---|---|---|---|
源程序 | .h、.cpp、.c | c\c++ | |
预处理 | .i | c\c++ | gcc/g++ -E src.c -o dest.i |
编译和优化 | .s | 汇编 | gcc/g++ -S src.i -o dest.s |
汇编 | .o | 二进制 | gcc/g++ -c src.s -o dest.o |
链接 | 默认 a.out | 二进制 | gcc/g++ src.o -o dest |
二、动态库和静态库
- 通常情况下,对函数库的链接是在编译时期完成的
- 根据链接阶段的处理方式,分为静态库和动态库
静态库 | 动态库 | ||
---|---|---|---|
前/后缀 | Linux | lib*.a | *.so |
Windows | *.lib | *.dll | |
生成 | 单个文件 | ar -rc libxxx.a xxx.o(正确方法) ar -rc libxxx.a xxx.c (链接报错) | gcc -fPIC -shared xxx.o -o xxx.so gcc -fPIC -shared xxx.c -o xxx.so |
多个文件 | ar -rc libxxx.a xxx1.o xxx2.o xxx3.o (正确方法) ar -rc libxxx.a xxx1.c xxx2.c xxx3.c (链接报错) | gcc -fPIC -shared xxx1.o xxx2.o xxx3.o -o libxxx.so gcc -fPIC -shared xxx1.c xxx2.c xxx3.c -o libxxx.so | |
链接 | g++ main.cpp -L./ -ltest -o main.exe -L : 指定静态库的搜索路径 -l : 指定静态库/动态库名称 | 与静态与用法类似 | |
对比 | 1. 代码装载、执行速度块 2. 应用程序相对较大,不同程序使用,多次装载 3. 函数库修改,程序重新编译 | 1. 多程序共享,只需将动态库加载到内存中一次即可 2. 函数库修改不影响程序 |
三、生成静态链接库
-
选择
Library --> C++ Library
-
类型设置为
Statically Linked Library
,并选择需要用到的Qt模块
-
pro文件说明
-
构建运行,生成lib*.a文件
四、生成动态链接库
- 创建步骤与静态链接库类似,将类型设置为
Shared Library
- 只要项目中有导出内容,整个项目(包括其他文件、其他对象)都会打包
# dllCreater.pro 文件中 添加自定义宏
TEMPLATE = lib
DEFINES += DLLCREATER_LIBRARY
// dllCreater.h -- 导出生成 dllCreater.dll
#if defined( _MSC_VER ) || defined( WIN64 ) || defined( _WIN64 ) || \
defined( __WIN64__ ) || defined( WIN32 ) || defined( _WIN32 ) || \
defined( __WIN32__ ) || defined( __NT__ )
#define Q_DECL_EXPORT __declspec( dllexport )
#define Q_DECL_IMPORT __declspec( dllimport )
#else
#define Q_DECL_EXPORT __attribute__( ( visibility( "default" ) ) )
#define Q_DECL_IMPORT __attribute__( ( visibility( "default" ) ) )
#endif
#if defined( DLLCREATER_LIBRARY )
#define DLLCREATER_EXPORT Q_DECL_EXPORT
#else
#define DLLCREATER_EXPORT Q_DECL_IMPORT
#endif
class DLLCREATER_EXPORT DllCreater {
public:
DllCreater(){};
};
/* 实际要导出的对象 */
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
namespace DLL {
void print( string words ) { cout << words << endl; }
void printDemo() { cout << "HELLO DLL" << endl; }
} // namespace DLL
# dllUser.pro 文件中,添加头文件路径和动态链接库
INCLUDEPATH += $$PWD/../dllCreater
LIBS += -L$$PWD/../dllCreater -ldllCreater
// dllUser.cpp
#include <QApplication>
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
namespace DLL {
void print( string words ) { cout << words << endl; }
void printDemo() { cout << "HELLO DLL" << endl; }
}
int main( int argc, char *argv[] ) {
Q_UNUSED( argc )
Q_UNUSED( argv )
DLL::print( "TEST DONE" );
DLL::printDemo();
return 0;
}
// 输出
// TEST DONE
// HELLO DLL
五、使用链接库
5.1 直接调用
- 修改pro文件
INCLUDEPATH += <path> # 头文件地址
LIBS += -L<path> -l<libName># 调用链接库
5.2 使用Qt的API调用
typedef bool ( *SetKeyBoardHook)(HWND); //定义函数指针
void MainWindow::test()
{
QLibrary mylib("dllhook");
if(mylib.load())
{
qDebug() << "dllhook加载成功";
SetKeyBoardHook open = (SetKeyBoardHook)mylib.resolve("SetKeyBoardHook");
if(open)
{
qDebug() << "SetKeyBoardHook加载成功";
bool flag = open((HWND)this->winId());
}
}
}