如何写DLL文件及调用DLL文件

来源:互联网 发布:表白视频制作软件 编辑:程序博客网 时间:2024/05/29 09:23

原文地址:http://panxianjin.dream.blog.163.com/blog/static/12635274620099293578769/


1.写DLL

打开VC++6.0,选择建立工程的动态链接库工程,建立一个Dll1的工程,写两个简单的函数,

如何写DLL文件及调用DLL文件 - cooler - endless.dream 的博客

注意此时函数并没有导出,所以是不能访问的,也是不能调用的,此时dll内部结构如下

如何写DLL文件及调用DLL文件 - cooler - endless.dream 的博客

可见没有显示可调用的函数。一定要加上_declspec(dllexport)表示导出函数,可供外面调用

如何写DLL文件及调用DLL文件 - cooler - endless.dream 的博客

此时add方法是可调用的,sub方法是不可调用的,dll内部结构此时如下

如何写DLL文件及调用DLL文件 - cooler - endless.dream 的博客

可以看到?add@@....,导出成功,这是c++为了支持多态按一定规则改变了函数名。而sub函数没有加_declspec(dllexport),因此外面是不能访问的,因此内部没有sub函数的名字。下面我们用extern “c”来试一下,看看函数名字结构是否会变化

如何写DLL文件及调用DLL文件 - cooler - endless.dream 的博客

内部结构如下:

如何写DLL文件及调用DLL文件 - cooler - endless.dream 的博客

可见add方法的名字存储确实改变了,下面我们用标准调用的存储方式试一下,加关键字_stdcall,同时对sub函数也导出,作比较。

如何写DLL文件及调用DLL文件 - cooler - endless.dream 的博客

内部结构:

如何写DLL文件及调用DLL文件 - cooler - endless.dream 的博客

看到add和sub都导出了,按标准调用和普通c调用的函数名如上图所示,标准调用函数名多了个@8,表示函数参数为8字节。

2.调用dll。

因为dll调用分为隐式调用和动态加载,隐式调用在程序运行时加载所有的dll提供的方法,内存开销较大,而动态加载只在需要时加载dll,然后释放掉,比较灵活。

1)隐式加载:(需要dll文件及lib文件)

说明:这里的lib文件并非静态库的Lib文件,这里的lib文件只提供了对应dll文件的一些相应方法,程序加载时是调用dll文件。

首先,建立一个简单的控制台工程test,然后拷贝Dll1.dll和Dll1.lib到test目录下,然后在setting的link里加上Dll1.lib,

如何写DLL文件及调用DLL文件 - cooler - endless.dream 的博客

程序如下:

如何写DLL文件及调用DLL文件 - cooler - endless.dream 的博客

结果如下:

如何写DLL文件及调用DLL文件 - cooler - endless.dream 的博客

2)动态加载只需(Dll1.dll文件)

代码如下:

如何写DLL文件及调用DLL文件 - cooler - endless.dream 的博客

通过<windows.h>的LoadLibrary()函数和GetProcAddress()函数动态获得函数的指针,然后就可以根据函数名调用相应的函数,MAKEINIRESOURCE()是更据函数的排列次序转换为函数的名字,一般不用这个方法。

上面也知道由于编译dll时函数的名字存储变化不定,动态加载时怎么知道函数名字是怎样的?因此当编译dll文件时,我们编写然后加入一个模块文件“dll文件名.def",然后把该文件加载到工程中,其内容如下(右边):

如何写DLL文件及调用DLL文件 - cooler - endless.dream 的博客

LIBRARY Dll1可以不要,EXPORTS必要,而且下面规定了dll里导出的函数存储为add和sub,不管你是按C++也好,C也好,标准调用也好,我只以add和sub方式存储。源文件如下:

如何写DLL文件及调用DLL文件 - cooler - endless.dream 的博客

加模块后的dll内部函数存储结构如下:

如何写DLL文件及调用DLL文件 - cooler - endless.dream 的博客

结果只按模块定义的形式存储。

 

 

把整个类都导出(类里所有的公有方法和属性外界可以访问):

声明为: class _declspec(dllexport) A

{

public:

private:

};

只导出某一个方法:

class A

{

  public:

  _declspec(dllexport) void get...();

}