WindowsC++静态库和动态库调用及导入导出

目录

1、静态库

1.1 条件

1.2 说明

2、动态库

2.1 条件

2.2 说明

3、代码举例

3.1 静态库

3.1.1 静态库头文件(CkxCaclulate.h)

3.1.2 静态库实现文件(CkxCaclulate.cpp)

3.1.3 调用

3.2 动态库静态调用

3.2.1 动态库头文件(CkxCalulate_Dll.h)

3.2.2 动态库实现文件(CkxCalulate_Dll.Cpp)

3.2.3 def文件(Test_Dll.def)

3.2.4 调用

3.3 动态链接库动态调用

3.3.1 动态库头文件

3.3.2 动态库实现文件

3.3.3 调用

3.4 工程全部代码

4、总结


1、静态库

1.1 条件

  • 头文件(.h)
  • 静态库文件(lib)

1.2 说明

        静态库的实现在lib中,调用者调用静态库时,将实现一起打包到链接到exe中,可实现随处编译随处运行,运行时无需提供其他文件

2、动态库

2.1 条件

  • 头文件(.h)
  • lib文件
  • dll文件

2.2 说明

1、动态库的调用分为静态调用和动态调用,静态调用编译时,需要同时提供上面三个文件,动态调用仅需提供dll文件

2、不管动态调用还是静态调用,都要实现供方(_declspec(dllexport))导出用方(_declspec(dllimport))导入

3、导出的方式有两种,一种是 extern "C" _declspec(dllexport),另一种是.def,两者等价

4、静态调用时,可用加extern "C"也可以不加,但在动态调用时必须加,否则使用原来的函数名无法调用;def方式动态调用和静态调用均可

5、.def和extern "C"的作用,都是防止函数名在导出时"乱码",从而防止动态调用时找不到函数名

3、代码举例

3.1 静态库

3.1.1 静态库头文件(CkxCaclulate.h)

#pragma once

//1、全局函数
int Add_Staic(int a, int b);
int Sub_Staic(int a, int b);

//2、全局变量

extern double g_Count_Static;
//类
class CkxCaclulate
{
public:
	CkxCaclulate(void);
	~CkxCaclulate(void);

	int Mul_Staic(int a, int b);
	int Div_Staic(int a, int b);
};


3.1.2 静态库实现文件(CkxCaclulate.cpp)

#include "CkxCaclulate.h"
#include <iostream>

using namespace  std;



double g_Count_Static = 10;

int Add_Staic(int a, int b)
{

	cout << "Add In Satic!"<<endl;
	return a + b;
}

int Sub_Staic(int a, int b)
{

	cout << "Sub In Satic!"<<endl;
	return a - b;
}

CkxCaclulate::CkxCaclulate(void)
{
}

CkxCaclulate::~CkxCaclulate(void)
{
}

int CkxCaclulate::Mul_Staic(int a, int b)
{

	cout << "Mul In Satic!"<<endl;
	return a*b;
}

int CkxCaclulate::Div_Staic(int a, int b)
{

	cout << "Div In Satic!"<<endl;
	return a/b;
}

3.1.3 调用

    #pragma comment(lib,"../Lib/Test_Static.lib")	//动态链接库
    静态链接库///
	cout<<"==================静态库调用===================================" << endl;
	//1、导入导出函数
	cout<<"Add(x,y) = "<< Add_Staic(x,y) << endl;
	cout<<"Sub(x,y) = "<< Sub_Staic(x,y) << endl;

	//2、导入导出类
	CkxCaclulate Caclulate;
	cout<<"Div(x,y) = "<< 	Caclulate.Div_Staic(x,y) << endl;
	cout<<"Mul(x,y) = "<< Caclulate.Mul_Staic(x,y) << endl;

	//3、导入导出全局变量
	cout<<"g_Count_Static = "<< g_Count_Static << endl;

3.2 动态库静态调用

3.2.1 动态库头文件(CkxCalulate_Dll.h)

#pragma once

#ifdef TEST_DLL_EXPORTS
#define API_CLASSEXT	_declspec(dllexport)
#define API_STDEXT		_declspec(dllexport)
#else
#define API_CLASSEXT	_declspec(dllimport)
#define API_STDEXT		_declspec(dllimport)
#endif

//1、全局函数
extern "C" API_STDEXT int Add(int a, int b);
extern "C" API_STDEXT int Sub(int a, int b);

/*API_STDEXT*/  int  Testdef(int a,int b);//def  等价于 extern "C" _declspec(dllexport)

//2、全局变量
extern  /*API_STDEXT*/ int g_Count_def;

extern  API_STDEXT double g_Count;

//3、类
 class API_CLASSEXT CkxCalulate_Dll
{
public:
	CkxCalulate_Dll(void);
	~CkxCalulate_Dll(void);

	int Mul(int a, int b);
	int Div(int a, int b);
};

3.2.2 动态库实现文件(CkxCalulate_Dll.Cpp)

#include "CkxCalulate_Dll.h"
#include <iostream>
using namespace  std;

double g_Count = 20;
int g_Count_def = 30;

int Add(int a, int b)
{
	cout << "Add In Dll!"<<endl;
	return a + b;
}

int Sub(int a, int b)
{
	cout << "Sub In Dll!"<<endl;
	return a - b;
}

int  Testdef(int a,int b)
{
	cout << "Testdef In Dll!"<<endl;
	return a%b;
}

CkxCalulate_Dll::CkxCalulate_Dll(void)
{
}

CkxCalulate_Dll::~CkxCalulate_Dll(void)
{
}

int CkxCalulate_Dll::Mul(int a, int b)
{

	cout << "Mul In Dll!"<<endl;
	return a*b;
}

int CkxCalulate_Dll::Div(int a, int b)
{

	cout << "Div In Dll!"<<endl;
	return a/b;
}

3.2.3 def文件(Test_Dll.def)

LIBRARY	"Test_Dll"

EXPORTS

Testdef
g_Count_def

3.2.4 调用

    #pragma comment(lib,"../Lib/Test_Dll.lib")		//动态链接库
    cout<<"==================动态库静态调用=================================== " << endl;
	//1、导入导出函数
	cout<<"Add(x,y) = "<< Add(x,y) << endl;
	cout<<"Sub(x,y) = "<< Sub(x,y) << endl;
	cout<<"Testdef(x,y) = "<< Testdef(x,y)<< endl;
	//2、导入导出类
	CkxCalulate_Dll Object;
	cout<<"Div(x,y) = "<< Object.Div(x,y) << endl;
	cout<<"Mul(x,y) = "<< Object.Mul(x,y) << endl;

	//3、导入导出全局变量
	cout<<"g_Count = "<<  g_Count << endl;
	cout<<"g_Count_def = "<<  g_Count_def << endl;

3.3 动态链接库动态调用

3.3.1 动态库头文件

同上

3.3.2 动态库实现文件

同上

3.3.3 调用

typedef int(*FUNA)(int,int);  //函数指针
cout<<"==================动态库动态调用=================================== " << endl;

	HMODULE hDLL = LoadLibrary(_T("Test_Dll.dll"));
	if (hDLL != NULL)
	{
		FUNA fp1 = (FUNA)(GetProcAddress(hDLL,"Add"));	//不加 extern "C"调用不成功
		if(fp1 != NULL)
		{
			fp1(x,y);
		}
		FUNA fp2 = (FUNA)(GetProcAddress(hDLL,"Testdef"));//不使用 .def 调用不成功
		if(fp2 != NULL)
		{
			fp2(x,y);
		}
	}

	FreeLibrary(hDLL);

3.4 工程全部代码

代码下载地址:https://download.csdn.net/download/vfw2014/88013826

4、总结

1、静态库的调用 需要 头文件、lib文件,lib文件中包含了实现,编译时,一起打包到调用者的exe中,应用程序可以单独运行
2、动态库的调用分为静态调用和动态调用。静态调用时,需要提供.h头文件、lib文件和dll文件;动态调用时仅需要提供dll文件
3、动态库的静态调用,需要将要导出的函数、数据成员、类增加 _declspec(dllexport)导出修饰,一般在头文件中使用宏定义 判断导入还是导出
4、extern "C" 和 .def文件用于防止函数名称被修改,可借助depend工具查看,不加exter "C"或未使用.def时,导出的函数名称“乱码名称”,如下图一
5、经测试仅动态库的动态调用才需要extern "C" 修饰导出或者使用.def,从而保证名称不被修改,静态调用加不加extern "C"也可以
6、.def  等价于  extern "C" _declspec(dllexport) 
7、添加.def 时要使用编译器自动添加,也可以手动添加,手动添加时,要注意关联def文件。见图二

                                                 图一

                                                         图二

  • 1
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值