You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1089 lines
24 KiB

3 years ago
---
title: dll生成与使用
date: 2022年4月28日
author: TianZD
top: true
cover: true
toc: true
mathjax: false
summary: dll是动态链接库,基于C++语言,使用不同的IDE进行测试使用
tags:
- C++
- DLL
categories:
- C++
abbrlink: fbf11e59
reprintPolicy: cc_by
coverImg:
img:
password:
---
[toc]
# DLL生成与使用(Clion、Visual Studio、QT Creator)
## DLL概述
3 years ago
概述内容[来自博客](https://blog.csdn.net/elaine_bao/article/details/51784864?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-6.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-6.pc_relevant_default&utm_relevant_index=12)
3 years ago
它们是一些独立的文件,其中包含能被可执行程序或其他dll调用来完成某项工作的函数,只有在其他模块调用dll中的函数时,dll才发挥作用。
在实际编程中,我们可以把完成某项功能的函数放在一个动态链接库里,然后提供给其他程序调用。像Windows API中所有的函数都包含在dll中,如Kernel32.dll, User32.dll, GDI32.dll等。那么dll究竟有什么好处呢?
### 静态库和动态库
#### 静态库
函数和数据被编译进一个二进制文件(扩展名通常为.lib)
在使用静态库的情况下,在编译链接可执行文件时,链接器从静态库中**复制这些函数和数据,并把它们和应用程序的其他模块组合起来创建最终的可执行文件(.exe)**。**当发布产品时,只需要发布这个可执行文件,并不需要发布被使用的静态库。**
#### 动态库
在使用动态库时,往往提供两个文件:**一个引入库(.lib,非必须)和一个.dll文件**。
这里的引入库和静态库文件虽然扩展名都是.lib,但是有着本质上的区别,对于一个动态链接库来说,**其引入库文件包含该动态库导出的函数和变量的符号名,而.dll文件包含该动态库实际的函数和数据。**
### 使用动态链接库的好处
- **可以使用多种编程语言编写**:比如我们可以用VC++编写dll,然后在VB编写的程序中调用它。
- **增强产品功能**:可以通过开发新的dll取代产品原有的dll,达到增强产品性能的目的。比如我们看到很多产品踢动了界面插件功能,允许用户动态地更换程序的界面,这就可以通过更换界面dll来实现。
- 提供二次开发的平台:用户可以单独利用dll调用其中实现的功能,来完成其他应用,实现二次开发。
- **节省内存**:如果多个应用程序使用同一个dll,该dll的页面只需要存入内存一次,所有的应用程序都可以共享它的页面,从而节省内存。
## Clion+msvc
生成的dll可以在使用同一编译器的不同sdk之间相互调用,但是要注意导出的是x86还是amd64
### 生成DLL
#### 新建项目
C++库-类型选择shared
![image-20220415075952640](https://gitee.com/tianzhendong/img/raw/master/images/202204280931661.png)
#### 新建文件
右键项目,新建C/C++源文件(或者直接新建一个类),并勾选创建关联头
![image-20220415080306293](https://gitee.com/tianzhendong/img/raw/master/images/202204161800789.png)
#### 编写c++
注意,类中的变量和函数只有public类型才可以被访问。
- 使用`__declspec(dllexport)`声明导出函数
- 使用`extern “C” __declspec(dllexport)`声明导出函数为c类型
`DllDemo.h`
```c
#ifndef DLLDEMO_DLLDEMO_H
#define DLLDEMO_DLLDEMO_H
#include <string>
#include <iostream>
using namespace std;
//使用__declspec(dllexport)声明导出函数
__declspec(dllexport) void sayHello();
__declspec(dllexport) int myAdd(int a, int b);
class __declspec(dllexport) Student{
public:
void setName(string name);
string getName();
void setAge(int age);
int getAge();
private:
string name;
int age;
};
#endif //DLLDEMO_DLLDEMO_H
```
`DllDemo.cpp`
```c
#include "DllDemo.h"
void sayHello(){
cout<<"hello!"<<endl;
}
int myAdd(int a, int b){
return a+b;
}
void Student::setName(string name) {
this->name = name;
}
string Student::getName() {
return this->name;
}
void Student::setAge(int age) {
this->age = age;
}
int Student::getAge() {
return this->age;
}
```
#### 构建
在debug目录下生成了.dll、.lib文件,后续主要用到.dll、.lib和.h文件
![image-20220415081755593](https://gitee.com/tianzhendong/img/raw/master/images/202204161800737.png)
### 测试
测试工具目录:
```bash
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin
```
win+r——cmd 进入上述目录
输入
```bash
VCVARS32.bat
```
然后进入dll文件所在目录
输入
```bash
dumpbin -exports Dll1.dll
```
### 使用dll
#### 新建项目
![image-20220415082005386](https://gitee.com/tianzhendong/img/raw/master/images/202204161800823.png)
#### 在项目根目录新建lib文件夹
将上述生成的.dll .lib 和编写的.h文件复制到lib中
![image-20220415104232406](https://gitee.com/tianzhendong/img/raw/master/images/202204161800779.png)
#### cmakelist.txt添加:
```cmake
cmake_minimum_required(VERSION 3.21)
project(DllUser)
set(CMAKE_CXX_STANDARD 14)
# 包含文件夹
include_directories(
src
lib
)
# 新增;指项目根目录下的lib目录
link_directories(lib)
add_executable(${PROJECT_NAME}
src/main.cpp)
# 新增;指目标链接的dll文件
target_link_libraries(${PROJECT_NAME}
DllDemo)
```
#### 运行/调试配置:
![image-20220415082456066](https://gitee.com/tianzhendong/img/raw/master/images/202204161801274.png)
#### 调用
> 方法1:lib中需要dll、lib和h三个文件
- 添加头文件
- 调用函数
```c
#include <iostream>
//添加头文件
#include "lib/DllDemo.h"
int main() {
sayHello();
cout<<myAdd(1,2)<<endl;
Student tian;
tian.setName("TianZD");
tian.setAge(18);
cout<<"tian'name:"<<tian.getName()<<endl;
cout<<"tian'age:"<<tian.getAge()<<endl;
return 0;
}
```
可以看到正确输出
> 方法2:lib中只需要dll文件
```c
#include <iostream>
#include <string>
using namespace std;
//#include "lib/DllDemo.h"
__declspec(dllimport) void sayHello();
__declspec(dllimport) class Student{
private:
string name;
int age;
public:
void setName(string name);
void setAge(int age);
string getName();
int getAge();
};
int main() {
sayHello();
Student tian;
tian.setName("TianZD");
tian.setAge(18);
cout<<"tian'name:"<<tian.getName()<<endl;
cout<<"tian'age:"<<tian.getAge()<<endl;
return 0;
}
```
### 多层调用
DllDemo1使用上面的
#### 新建DllDemo2 Dll文件
#### 将DllDemo1的dll、lib、h文件放入lib中
#### 编写DllDemo2.h和.cpp
##### 情况一:2的h中没有引入1的内容,cpp中引入
```c
#ifndef DLLDEMO2_DLLDEMO2_H
#define DLLDEMO2_DLLDEMO2_H
//#include "DllDemo.h"
__declspec(dllexport) void sayHello2();
__declspec(dllexport) int myAdd2(int a, int b);
//class __declspec(dllexport) Student2: Student{
//public:
// void setAge2(int age);
// int getAge2();
//private:
// int age2;
//};
#endif //DLLDEMO2_DLLDEMO2_H
```
```c
#include "DllDemo2.h"
#include "DllDemo.h"
#include <iostream>
using namespace std;
void sayHello2(){
cout<<"hello2222"<<endl;
sayHello();
Student tian;
tian.setName("dlldemo2");
cout<<tian.getName()<<endl;
}
int myAdd2(int a, int b){
return myAdd(a,b);
}
//
//void Student2::setAge2(int age) {
// this->age2 = age;
//}
//
//int Student2::getAge2() {
// return this->age2;
//}
```
##### 情况二:2的h中引入了1的内容
```c
#ifndef DLLDEMO2_DLLDEMO2_H
#define DLLDEMO2_DLLDEMO2_H
#include "DllDemo.h"
__declspec(dllexport) void sayHello2();
class __declspec(dllexport) Student2: Student{
public:
void setAge2(int age);
int getAge2();
private:
int age2;
};
#endif //DLLDEMO2_DLLDEMO2_H
```
```c
#include "DllDemo2.h"
void sayHello2(){
cout<<"hello2222"<<endl;
sayHello();
}
void Student2::setAge2(int age) {
this->age2 = age;
}
int Student2::getAge2() {
return this->age2;
}
```
#### cmaklists.txt
```cmake
cmake_minimum_required(VERSION 3.21)
project(DllDemo2)
set(CMAKE_CXX_STANDARD 14)
include_directories(
src
lib
)
# 新增;指项目根目录下的lib目录
link_directories(
lib
)
add_library(${PROJECT_NAME} SHARED
"src/library.cpp"
"src/DllDemo2.cpp"
"src/DllDemo2.h")
# 新增;指目标链接的dll文件
target_link_libraries(${PROJECT_NAME}
DllDemo
)
```
#### 添加lib到编译器的环境变量中
#### 使用
##### 情况一:2的h中没有引入1的内容,cpp中引入了
只需要将1的dll和2的三个文件放入lib中
添加lib环境变量
cmake
```cmake
cmake_minimum_required(VERSION 3.21)
project(DllUser2)
set(CMAKE_CXX_STANDARD 14)
include_directories(
src
lib
)
# 新增;指项目根目录下的lib目录
link_directories(lib)
add_executable(${PROJECT_NAME}
src/main.cpp)
# 新增;指目标链接的dll文件
target_link_libraries(${PROJECT_NAME}
#只需要dlldemo2
DllDemo2)
```
测试
```c
#include <iostream>
#include "DllDemo2.h"
int main() {
std::cout << "Hello, World!" << std::endl;
sayHello2();
std::cout<<myAdd2(1,2);
return 0;
}
```
![image-20220415131004040](https://gitee.com/tianzhendong/img/raw/master/images/202204161801691.png)
##### 情况二:2的h中引入1
将1和2的三个文件(dll、lib、h)均放入到lib中
添加lib目录环境变量
添加cmakelists.txt
```cmake
cmake_minimum_required(VERSION 3.21)
project(DllUser2)
set(CMAKE_CXX_STANDARD 14)
include_directories(
src
lib
)
# 新增;指项目根目录下的lib目录
link_directories(lib)
add_executable(${PROJECT_NAME}
src/main.cpp)
# 新增;指目标链接的dll文件
target_link_libraries(${PROJECT_NAME}
DllDemo
DllDemo2)
```
调用
```c
#include <iostream>
#include "DllDemo2.h"
int main() {
std::cout << "Hello, World!" << std::endl;
Student tian;
tian.setAge(12);
cout<<tian.getAge()<<endl;
Student2 tian2;
tian2.setAge2(123);
cout<<tian2.getAge2()<<endl;
sayHello2();
return 0;
}
```
## Visual Studio + msvc(c++)
参考[博客](https://blog.csdn.net/freeking101/article/details/104632710/?utm_medium=distribute.wap_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-1.wap_blog_relevant_default&spm=1001.2101.3001.4242.2&utm_relevant_index=4)
> 可以直接调用clion生成的dll
>
> 生成平台X86、X64要注意,要和要调用该DLL的平台保持一直
### 生成dll
把 函数 声明放在 .h 中,函数定义放在 cpp 文件中。
#### 新建项目
选择`具有导出项的DLL动态链接库`
![image-20220415205304326](https://gitee.com/tianzhendong/img/raw/master/images/202204161801655.png)
![image-20220415205923849](https://gitee.com/tianzhendong/img/raw/master/images/202204161801582.png)
#### 导出
##### 声明导出
头文件
```c
// 以c方式导出
extern "C" __declspec(dllexport) void hello();
// 以c++方式导出
__declspec(dllexport) void hello1();
//以.def方式导出
void hello2();
```
源文件
```c
#include "pch.h"
#include "framework.h"
#include "Dll2.h"
#include <iostream>
void hello() {
std::cout << "hello" << std::endl;
}
void hello1() {
std::cout << "hello11" << std::endl;
}
void hello2() {
std::cout << "hello2" << std::endl;
}
```
然后点击 “ 生成解决方案 ” ,就可以在工程目录的 debug 目录或者 release 目录下(这取决你生成的是debug版本还是release版本)生成了动态链接库的相关文件。第三方调用时关键的文件为 **.lib文件** 和 **.dll文件** 以及工程目录下的 **.h头文件** 。
##### 模板定义方式导出
在项目中定义.def 文件,该文件为模块导出文件
![image-20220415210130710](https://gitee.com/tianzhendong/img/raw/master/images/202204161801369.png)
编写.def
```c
LIBRARY
EXPORTS
hello2
```
如果是vs平台,需要在连接器中添加.def文件,如果是通过上述方式添加的.def,会自动添加
![image-20220415210911123](https://gitee.com/tianzhendong/img/raw/master/images/202204161801001.png)
然后点击 “ 生成解决方案 ” ,就可以在工程目录的 debug 目录或者 release 目录下(这取决你生成的是debug版本还是release版本)生成了动态链接库的相关文件。第三方调用时关键的文件为 **.lib文件** 和 **.dll文件** 以及工程目录下的 **.h头文件**
![image-20220415211216385](https://gitee.com/tianzhendong/img/raw/master/images/202204161801637.png)
### 调用
#### 新建C++控制台应用
#### 将dll放在debug目录下,将h和lib放在可以找到的位置
.dll文件是程序运行需要载入的动态链接库,VS中调试时可以通过 项目->属性->调试->环境 栏目添加.dll文件的 path 而成功调试,但在独立运行.exe程序是须将.dll文件放到同一目录下。
​ 因此建议直接将 .dll文件 放入debug目录下或release目录下。.h头文件 和 .lib库文件 可以随意放置,只要是能够通过路径找到即可,为了方便管理,建议建立文件夹,放置在项目目录下。
#### 调用
可以直接调用Clion生成的Dll,应该只与编译器有关(用的都是同一个版本的msvc)
##### 直接添加引用
```c
#include <iostream>
#include "Dll2.h"//通过相对路径或绝对路径添加头文件
#pragma comment (lib,"Dll2.lib") // 添加 lib 文件
int main()
{
std::cout << "Hello World!\n";
hello();
hello1();
hello2();
}
```
![image-20220415211932141](https://gitee.com/tianzhendong/img/raw/master/images/202204161801293.png)
##### 在解决方案管理面板中添加头文件和资源文件
添加一个现有项头文件,在文件夹中找到第三方库的头文件( .h ),添加进新建立的项目。
添加一个现有项资源文件,在文件夹中找到第三方库的库文件( .lib ),添加进新建立的项目。
![image-20220415212042047](https://gitee.com/tianzhendong/img/raw/master/images/202204161801281.png)
```c
#include <iostream>
#include "Dll2.h"//通过相对路径或绝对路径添加头文件
//#pragma comment (lib,"Dll2.lib") // 添加 lib 文件
int main()
{
std::cout << "Hello World!\n";
hello();
hello1();
hello2();
}
```
##### 在 项目属性 -> 设置 中 添加 头文件 和 库文件
* 项目->属性->VC++目录->包含目录 中添加第三方库的 **头文件**
* 库目录 下 添加 第三方库 的 **库文件(.lib文件)**
* 项目->属性->链接器->输入->附加依赖项中输入 **库文件名称**
##### 直接在代码load动态库文件
这种方法不需要 include .h文件,不需要添加 lib库 和 lib库路径,
* 引入 windows.h(必须)
* 在 main 函数写下列语句调用 dll
​ 因为 C++ 声明 的 动态链接库会发生 Name Mangling,导致 编译后的函数名字会发生变化,所以需要使用 工具 查看 编译编译后的 动态链接库 对应的函数名。
​ 而 extern "C" 声明的 和 def 文件声明的,编译后的函数名不会发生变化,可以直接使用。
VS2019 自带的工具 dumpbin.exe 可以查看编译后的 动态链接库对应的 函数名。
![image-20220415212305795](https://gitee.com/tianzhendong/img/raw/master/images/202204161801247.png)
打开命令行,输入命令 `dumpbin -exports Dll2.dll`
这里采用博客中的内容:
![img](https://gitee.com/tianzhendong/img/raw/master/images/202204161801007.png)
所以 addFunc 不能直接使用,只能用被 name Mangling 后的名字 ,这里 **addFunc** 编译后的名字是 **?addFunc@@YAHHH@Z**
```c
#include <iostream>
#include <windows.h>
// 加、减、乘 都是 int 类型
typedef int(*lpFunc)(int a, int b); //后边为参数,前面为返回值
// 除法 是 double 类型
typedef double(*lpFuncD)(double a, double b); //后边为参数,前面为返回值
int main()
{
std::cout << "Hello World!\n";
HMODULE hModule;
hModule = LoadLibrary(L"CPPDLL.dll"); //调用DLL
lpFunc lpfunc = NULL;
// GetProcAddress为获取该函数的地址
// "?addFunc@@YAHHH@Z" 这个就是 C++ Name Mangling后的 addFunc 的函数名
lpfunc = (lpFunc)GetProcAddress(hModule, "?addFunc@@YAHHH@Z");
std::cout << lpfunc(1, 2) << std::endl;
/* 使用 C extern 和 def 文件定义的动态链接库,函数名不会发生变化 */
lpfunc = (lpFunc)GetProcAddress(hModule, "subFunc");
std::cout << lpfunc(3, 4) << std::endl;
lpfunc = (lpFunc)GetProcAddress(hModule, "mulFunc");
std::cout << lpfunc(5, 6) << std::endl;
lpFuncD lpfuncd = NULL;
lpfuncd = (lpFuncD)GetProcAddress(hModule, "divFunc");
std::cout << lpfuncd(7, 8) << std::endl;
//释放
FreeLibrary(hModule);
}
```
##### 使用lib和dll文件
***CPPDLL.dll** 文件放到 debug 目录下,
* 然后在项目中引入 **CPPDLL.lib** 文件。 **链接器** -> **输入** -> **附加依赖项** -> **编辑**
![img](https://gitee.com/tianzhendong/img/raw/master/images/202204161802483.png)
```c
#include <iostream>
// addFunc 是使用 C++ 方式声明的,
_declspec(dllimport) int addFunc(int a, int b);
//subFunc 是 使用 extern "C" 声明的
extern "C" _declspec(dllimport) int subFunc(int a, int b);
// mulFunc 和 divFunc 是 使用 def 声明的
_declspec(dllimport) int mulFunc(int a, int b);
_declspec(dllimport) double divFunc(double a, double b);
int main()
{
std::cout << "Hello World!\n";
std::cout << addFunc(1, 2) << std::endl;
std::cout << subFunc(3, 4) << std::endl;
std::cout << mulFunc(5, 6) << std::endl;
std::cout << divFunc(7, 8) << std::endl;
return 0;
}
```
还可以结合 **第一种方法**,使用 **#pragma comment (lib,"./CPPDLL.lib")** //添加 lib 文件
这样就不用 手动设置 添加 lib 文件了
#### 多层调用
只需要把多层的dll都放进去即可
## VisualStudio (c#)调用c++的DLL
> 个人一般只用c#调用c++代码
>
> 可以直接调用Clion生成的DLL,但是只能调用**extern “C”声明的导出函数**
注意:一般msvc版本是X86的,要注意,使用x64位的netCore无法调用,这里我用的是netFramwork
### 生成DLL
使用Clion,也可以使用visualStudion,生成方法同上,这里只列出代码部分
#### 第一层:
```c
#ifndef DLLDEMO_DLLDEMO_H
#define DLLDEMO_DLLDEMO_H
#include <string>
#include <iostream>
using namespace std;
extern "C" __declspec(dllexport) void sayHello();
__declspec(dllexport) void sayHello1();
extern "C" __declspec(dllexport) int myAdd(int a, int b);
class Student{
public:
string name;
void studentHello();
};
#endif //DLLDEMO_DLLDEMO_H
```
```c
#include "DllDemo.h"
void Student::studentHello() {
cout<<"studentHello"<<endl;
}
void sayHello(){
Student s;
s.studentHello();
cout<<"hello1111111!"<<endl;
}
void sayHello1(){
Student s;
s.studentHello();
cout<<"hello1111111!"<<endl;
}
int myAdd(int a, int b){
return a+b;
}
```
#### 第二层
将1的三个文件放入lib
配置编译器lib环境变量
添加cmakelists.txt
编写调用代码
```c
//
// Created by 12038 on 2022/4/15.
//
#ifndef DLLDEMO2_DLLDEMO2_H
#define DLLDEMO2_DLLDEMO2_H
//#include "DllDemo.h"
extern "C" __declspec(dllexport) void sayHello2();
extern "C" __declspec(dllexport) int myAdd2(int a, int b);
class Student2{
public:
void student2Hello();
};
#endif //DLLDEMO2_DLLDEMO2_H
```
```c
//
// Created by 12038 on 2022/4/15.
//
#include "DllDemo2.h"
#include "DllDemo.h"
#include <iostream>
using namespace std;
void sayHello2(){
cout<<"hello2222"<<endl;
sayHello();
Student2 tian;
tian.student2Hello();
}
int myAdd2(int a, int b){
return myAdd(a,b);
}
//
void Student2::student2Hello() {
cout<<"student22222Hello"<<endl;
}
```
### visual studio调用
### 建立netframework项目
![image-20220415183057359](https://gitee.com/tianzhendong/img/raw/master/images/202204161802422.png)
### 将两个dll文件放到debug目录下
![image-20220415183130534](https://gitee.com/tianzhendong/img/raw/master/images/202204161802830.png)
### 调用
添加`using System.Runtime.InteropServices;`
导入库文件`[DllImport("DllDemo2.dll")]`
导入函数`private static extern void sayHello2();`
```c#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//添加相应的库
using System.Runtime.InteropServices;
namespace ConsoleApp3
{
class Program
{
//调用
[DllImport("DllDemo2.dll")]
private static extern void sayHello2();
[DllImport("DllDemo2.dll")]
private static extern int myAdd2(int a, int b);
static void Main(string[] args)
{
//使用
sayHello2();
Console.WriteLine(myAdd2(1, 2));
}
}
}
```
## QT Creator + msvc
### 生成dll
- 新建dll项目
![image-20220416163601291](https://gitee.com/tianzhendong/img/raw/master/images/202204161802876.png)
![image-20220416163629764](https://gitee.com/tianzhendong/img/raw/master/images/202204161802629.png)
![image-20220416163646551](https://gitee.com/tianzhendong/img/raw/master/images/202204161802040.png)
生成后的结构如下(这里用的的DllDemo1):
![image-20220416171503348](https://gitee.com/tianzhendong/img/raw/master/images/202204161802235.png)
其中_global.h自带两个系统默认导出宏
```c
#ifndef DLLDEMO1_GLOBAL_H
#define DLLDEMO1_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(DLLDEMO1_LIBRARY)
# define DLLDEMO1_EXPORT Q_DECL_EXPORT
#else
# define DLLDEMO1_EXPORT Q_DECL_IMPORT
#endif
#endif // DLLDEMO1_GLOBAL_H
```
- 编写导出函数
头文件:
```c
#ifndef DLLDEMO1_H
#define DLLDEMO1_H
#include "DllDemo1_global.h"
class DLLDEMO1_EXPORT DllDemo1
{
public:
DllDemo1();
};
//声明导出的函数sayhello
DLLDEMO1_EXPORT void sayHello();
//声明导出的函数myadd
DLLDEMO1_EXPORT int myAdd(int a, int b);
#endif // DLLDEMO1_H
```
源文件:
```c
#include "dlldemo1.h"
#include <iostream>
DllDemo1::DllDemo1()
{
}
//实现函数
void sayHello(){
std::cout<<"hello, dll in qt"<<std::endl;
}
int myadd(int a, int b){
std::cout<<"myadd"<<std::endl;
return a+b;
}
```
构建后会在debug目录下生成**dll和lib文件,同时可能需要用到.h和_global.h文件**
### 调用
#### 新建c++控制台项目
![image-20220416172129620](https://gitee.com/tianzhendong/img/raw/master/images/202204161802293.png)
#### 构建项目,生成debug目录
#### 将dll文件放到debug目录
![image-20220416172227912](https://gitee.com/tianzhendong/img/raw/master/images/202204161802638.png)
#### 将lib文件放到工程目录下
![image-20220416172258532](https://gitee.com/tianzhendong/img/raw/master/images/202204161802366.png)
#### 右键项目,添加lib库
![](https://gitee.com/tianzhendong/img/raw/master/images/202204161802541.png)
**选择外部库**
选择刚才的lib文件,取消平台下的linux,mac,取消为debug版本添加d作为哦后缀,点击完成代码就被添加进call.pro
![image-20220416172524995](https://gitee.com/tianzhendong/img/raw/master/images/202204161808242.png)
#### 调用
- 方法1:
```c
#include <QCoreApplication>
#include<iostream>
using namespace std;
__declspec(dllimport) void sayHello();
__declspec(dllimport) int myAdd(int a, int b);
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
cout<<myAdd(1,2)<<endl;
sayHello();
return a.exec();
}
```
- 方法2
将.h和_global.h放入到项目目录下
右键项目,添加两个.h文件
![image-20220416175017723](https://gitee.com/tianzhendong/img/raw/master/images/202204161802804.png)
引入头文件
```c
#include <QCoreApplication>
#include<iostream>
//引入头文件
#include "./dlldemo1.h"
using namespace std;
//__declspec(dllimport) void sayHello();
//__declspec(dllimport) int myAdd(int a, int b);
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
cout<<myAdd(1,2)<<endl;
sayHello();
return a.exec();
}
```