vs2019生成dll并调用的实现示例:https://www.jb51.net/article/179759.htm

 

vs2017创建linux c++程序:https://blog.csdn.net/qingyulove/article/details/86659726

vs2019编写Linux c/c++项目:https://blog.csdn.net/mmmsss987/article/details/103518996

Visual Studio 2019 基于Linux平台的C++开发:https://www.cnblogs.com/sgawscd/p/12916544.html

 

 

1. VS 中生成动态链接库的三种方式(导出函数)

 

开发环境:VS2019

 

创建动态链接库项目

新建项目,搜索 DLL ,选择 “ 具有导出项的(DLL)动态链接库 ”,

输入项目名称,选择项目所在目录,然后点击 创建

生成如下图所示的文件结构:

 

 

导出动态链接库

 

方法一 :声明导出

 

1、以 C++ 的方式声明导出。

在 CPP_DLL.cpp 文件中添加下面的函数,在函数声明前添加 _declspec(dllexport) 关键字

// C++ 的方式声明导出
_declspec(dllexport) int addFunc(int a, int b);
int addFunc(int a, int b)
{
    return a + b;
}

示例截图:

 

2、以 C 的方式声明导出。

在 CPP_DLL.cpp 文件中添加下面的函数,在函数声明前添加 extern "C"  _declspec(dllexport) 关键字

// C 的方式声明导出
extern "C"
{
	_declspec(dllexport) int subFunc(int a, int b);
	int subFunc(int a, int b)
	{
		return a + b;
	}

}

示例截图:

然后点击 “ 生成解决方案 ” ,就可以在工程目录的 debug 目录或者 release 目录下(这取决你生成的是debug版本还是release版本)生成了动态链接库的相关文件。第三方调用时关键的文件为 .lib文件.dll文件 以及工程目录下的 .h头文件

 

 

方法二: 模块定义文件导出

在项目中定义CPP_DLL.def 文件,该文件为模块导出文件

在 CPP_DLL.cpp 文件中添加下面的函数

LIBRARY
EXPORTS
  mulFunc
  divFunc

示例截图:

 

如果是 VS 平台,必须要在 连接器 中添加 .def 文件

然后点击 “ 生成解决方案 ” ,就可以在工程目录的 debug 目录或者 release 目录下(这取决你生成的是debug版本还是release版本)生成了动态链接库的相关文件。第三方调用时关键的文件为 .lib文件.dll文件 以及工程目录下的 .h头文件

对应 的 DLL 和 lib 文件

 

 

 

2. 调用前面开发的动态链接库

 

1. 新建一个C/C++项目(test)

 

 

2. 将第三方库的 .h文件、.lib文件、.dll文件 复制进工程项目中

        .dll文件是程序运行需要载入的动态链接库,VS中调试时可以通过 项目->属性->调试->环境 栏目添加.dll文件的 path 而成功调试,但在独立运行.exe程序是须将.dll文件放到同一目录下。

        因此建议直接将 .dll文件 放入debug目录下或release目录下.h头文件.lib库文件 可以随意放置,只要是能够通过路径找到即可,为了方便管理,建议建立文件夹,放置在项目目录下。

 

 

3. 在项目中调用第三方库

 

有三种方法可以调用第三方库。

 

(1)直接在代码前添加引用

因为直接引用 CPPDLL.h 头文件,所以需要把 动态链接库的 函数声明放在头文件中。

修改 CPP_DLL 的 .h 文件 和 cpp 文件,把 函数 声明放在 .h 中,函数定义放在 cpp 文件中。

CPP_DLL.h

// C++ 的方式声明导出
_declspec(dllexport) int addFunc(int a, int b);

// C 的方式声明导出
extern "C"
{
	_declspec(dllexport) int subFunc(int a, int b);
}

int mulFunc(int a, int b);
double divFunc(double a, double b);

CPP_DLL.cpp

int addFunc(int a, int b)
{
    return a + b;
}

int subFunc(int a, int b)
{
	return a - b;
}


// def 文件形式
int mulFunc(int a, int b)
{
	return a * b;
}

double divFunc(double a, double b)
{
	return a / b;
}

重新生成 DLL 文件,并将 DLL  、lib 、.h 文件拷贝到对应目录

 

C++ 测试代码:

#include <iostream>
#include "./CPP_DLL.h"   //通过相对路径或绝对路径添加头文件
#pragma comment (lib,"./CPPDLL.lib")  // 添加 lib 文件


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;
}

运行结果截图:

 

 

(2)在解决方案管理面板中添加头文件和资源文件

添加一个现有项头文件,在文件夹中找到第三方库的头文件( CPP_DLL.h ),添加进新建立的项目。
添加一个现有项资源文件,在文件夹中找到第三方库的库文件( CPPDLL.lib ),添加进新建立的项目。

 

 

(3)在 项目属性 -> 设置 中 添加 头文件库文件

  • 项目->属性->VC++目录->包含目录 中添加第三方库的 头文件
  • 库目录 下 添加 第三方库 的 库文件(.lib文件)
  • 项目->属性->链接器->输入->附加依赖项中输入 库文件名称

在函数中调用第三方库中的函数

#include <iostream>


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;
}

 

 

4. 直接在代码里 load 动态库dll文件即可

这种方法不需要 include .h文件,不需要添加 lib库 和 lib库路径,

  • 引入 windows.h(必须)
  • 在 main 函数写下列语句调用 dll

        因为 C++ 声明 的 动态链接库会发生 Name Mangling,导致 编译后的函数名字会发生变化,所以需要使用 工具 查看 编译编译后的 动态链接库 对应的函数名。

        而 extern "C" 声明的 和 def 文件声明的,编译后的函数名不会发生变化,可以直接使用。

VS2019 自带的工具 dumpbin.exe 可以查看编译后的 动态链接库对应的 函数名。

打开命令行,输入命令 dumpbin -exports CPPDLL.dll

结果截图:

所以 addFunc 不能直接使用,只能用被 name Mangling 后的名字 ,这里  addFunc 编译后的名字是 ?addFunc@@YAHHH@Z

示例程序代码:

#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);	
}

运行结果:

 

 

方法 5:使用 lib 文件 和 dll 文件

  • CPPDLL.dll 文件放到 debug 目录下,
  • 然后在项目中引入 CPPDLL.lib 文件。 链接器 -> 输入 -> 附加依赖项 -> 编辑

示例代码:

#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 文件了

#include <iostream>
#pragma comment (lib,"./CPPDLL.lib")


// addFunc 是使用 C++ 方式声明的,
_declspec(dllimport) int addFunc(int a, int b);  // 声明 addFunc 函数

//subFunc 是 使用 extern "C" 声明的
extern "C" _declspec(dllimport) int subFunc(int a, int b);  // 声明 subFunc 函数

// mulFunc 和 divFunc 是 使用 def 声明的
_declspec(dllimport) int mulFunc(int a, int b);             // 声明 mulFunc 函数
_declspec(dllimport) double divFunc(double a, double b);    // 声明 divFunc 函数


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;
}

 

 

 

 

 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐