动态链接库理解(二)

1、在(一)我们提到C++编译器在导出函数的时候,会对函数做名字改编,这样的话,我们用C++编写的dll,拿给C语言,或C#语言的客户端程序调用就会出问题。因为名字发生了改变,会找不到。

所以我们希望在输出函数名的时候,名字最好不要发生改变。但是怎么办呢?

(1)只需要将(一)中的Dll1.h中的

#define DLL1_API _declspec(dllimport)
变为
#define DLL1_API extern "C" _declspec(dllimport)

(2)将Dll1.cpp中的

#define DLL1_API _declspec(dllexport)

   变为

#define DLL1_API extern "C" _declspec(dllexport)

我们可以用dumpbin查看,名字有没有改变(dumpbin使用,参考(一))。

2、但是extern "C"不能导出一个类的成员函数,只能导出成员函数。并且在导出函数的调用约定发生变化的时候,即使用了extern "C"那么函数的名字也会发生改变,extern "C"只能用于C调用约定的时候,如果是_stdcall标准调用约定,有extern "C",函数名也会发生改变。那么问题来了,怎么办呢?

使用模块定义文件的方式解决这个名字改编的问题。具体步骤:

(1)新建一个dll工程Dll2,在工程目录下建立一个.def文件,将文件加入到工程中,工程--添加到工程--文件--.def文件

(2).def文件中写:

LIBRARYDll2//工程名

EXPORTS //更多EXPORTS功能参看MSDN

add //要导出的函数名

subtract //要导出的函数名

3、如何动态加载动态链接库?

动态加载的好处:节省资源

坏处:需要手动添加,如果加入很多的dll,则会特别麻烦。

<span style="white-space:pre">	</span>HINSTANCE hInst;
	hInst=LoadLibrary("Dll3.dll");//加载dll
	typedef int (/*_stdcall*/*ADDPROC)(int a,int b);//定义函数指针	
	//_stdcall则说明函数的定义使用的是标准调用约定,所以在这也需要声明_stdcall
	ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"add");
	//得到导出函数的地址
	//ADDPROC Add=(ADDPROC)GetProcAddress(hInst,MAKEINTRESOURCE(1));//用序号访问
	if(!Add){MessageBox("获取函数地址失败!");return;}
	CString str;str.Format("5+3=%d",Add(5,3));
	MessageBox(str);FreeLibrary(hInst);




 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值