博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
实例讲解动态链接库的开发
阅读量:6291 次
发布时间:2019-06-22

本文共 4187 字,大约阅读时间需要 13 分钟。

静态库是函数和数据被编译进一个二进制文件中(通常扩展名为.lib)。在使用静态库的情况下,在编译链接可执行文件时,链接器从库中复制这些函数和数据并把它们和应用程序的其它模块组合起来创建最终的可执行文件(.EXE文件)
     
动态链接库通常都不能直接运行,也不能接收消息。它们是一些独立的文件,其中包含能被可执行程序或其它DLL调用来完成某项工作的函数。只有在其它模块调用动态链接库中的函数时,它才发挥作用。在使用动态库的时候,往往提供两个文件:一个引入库和一个DLL。引入库包含被DLL导出的函数和变量的符号名,DLL包含实际的函数和数据。在编译链接可执行文件时,只需要链接引入库,DLL中的函数代码和数据并不复制到可执行文件中,在运行的时候,再去加载DLL,访问DLL中导出的函数。
    
动态链接库加载的两种方式:隐式链接,显示加载。关于这两种加载方式的实例说明,请见我的另一篇文章《》。以下所有说明均采用隐式链接方式,开发环境为VC
  • 下面说说函数的导出:
创建源文件如下:
_declspec(dllexport) int    add(int a,int b) 


return a+b; 



_declspec(dllexport) int    subtract(int a,int b) 


return a-b; 

}
 
观察编译之后,我们看到了导出函数,只是名字被更改了:
Dump of file dll1.dll 


File Type DLL 


    Section contains the following exports for Dll1.dll 


                     0 characteristics 

        456BD6E2 time date stamp Tue Nov 28 142746 2006 

                0.00 version 

                     1 ordinal base 

                     2 number of functions 

                     2 number of names 


        ordinal hint RVA            name 


                    1        0 0000100A add@@YAHHH@Z 

                    2        1 00001005 subtract@@YAHHH@Z 


    Summary 


                7000 .data 

                1000 .idata 

                3000 .rdata 

                2000 .reloc 

             2A000 .text
 
将刚刚生成动态链接库文件的同一目录下,找到dll1.lib输入库文件,拷贝到我们的工程目录下。此时,我们就可以在应用程序中使用dll1库了。
  #include iostream.h 

extern int add(int,int);     声明这个函数在外部定义 

extern int subtract(int,int); 

_declspec(dllimport) int add(int,int); 

_declspec(dllimport) int subtract(int,int); 

void main(void) 


cout3+5 = add(3,5)endl; 

cout5-3 = subtract(5,3)endl; 

}
  • 下面谈谈关于类的导出:
将整个类都导出:
#ifdef DLL1_API 

#else 

#define DLL1_API _declspec(dllimport) 

#endif 

DLL1_API int add(int,int); 

DLL1_API int subtract(int,int); 

class DLL1_API Point 


public 

void output( int x,int y); 

};
 
如果不想将整个类都导出,只将类的部分共有成员函数导出,则可以采用下面的方法:
#ifdef DLL1_API 

#else 

#define DLL1_API _declspec(dllimport) 

#endif 

DLL1_API int add(int,int); 

DLL1_API int subtract(int,int); 

class DLL1_API Point 


public 

DLL1_API void output( int x,int y); 

void test(); 

};
 
看一下库的导出情况
Dump of file dll1.dll 


File Type DLL 


    Section contains the following exports for Dll1.dll 


                     0 characteristics 

        456BE737 time date stamp Tue Nov 28 153727 2006 

                0.00 version 

                     1 ordinal base 

                     3 number of functions 

                     3 number of names 


        ordinal hint RVA            name 


                    1        0 00001019 add@@YAHHH@Z 

                    2        1 0000101E output@Point@@QAEXHH@Z 

                    3        2 00001014 subtract@@YAHHH@Z 


    Summary 


                7000 .data 

                1000 .idata 

                3000 .rdata 

                2000 .reloc 

             31000 .text
 
上面提到了VC++编译器将函数名字进行了改写,这对于其他编译器来说也许就不是什么好事,因为其他编译器很可能找不到导出的函数,因为名字被改动了。
  • 不改变导出函数名称,保证其他编译器可以使用链接库:
如果不希望改变导出函数的名称,可以加上 extern C 标识
dll1.cpp 

#define DLL1_API extern C _declspec(dllexport) 

#include dll1.h 

int    add(int a,int b) 


return a+b; 


int    subtract(int a,int b) 


return a-b; 



dll1.h 

#ifdef DLL1_API 

#else 

#define DLL1_API extern C _declspec(dllimport) 

#endif 

DLL1_API int add(int,int); 

DLL1_API int subtract(int,int);
 
再看一下导出发现名字没有改变:
Dump of file dll1.dll 


File Type DLL 


    Section contains the following exports for Dll1.dll 


                     0 characteristics 

        456BE969 time date stamp Tue Nov 28 154649 2006 

                0.00 version 

                     1 ordinal base 

                     2 number of functions 

                     2 number of names 


        ordinal hint RVA            name 


                    1        0 0000100A add 

                    2        1 00001005 subtract 


    Summary 


                7000 .data 

                1000 .idata 

                3000 .rdata 

                2000 .reloc 

                2A000 .text
 
extern C
dll1.cpp 

#define DLL1_API extern C _declspec(dllexport) 

#include dll1.h 

int _stdcall    add(int a,int b) 


return a+b; 


int _stdcall    subtract(int a,int b) 


return a-b; 



dll1.h 

#ifdef DLL1_API 

#else 

#define DLL1_API extern C _declspec(dllimport) 

#endif 

DLL1_API int _stdcall add(int,int); 

DLL1_API int _stdcall subtract(int,int);
 
采用_stdcall调用约定后的导出情况:
Dump of file dll1.dll 


File Type DLL 


    Section contains the following exports for Dll1.dll 


                     0 characteristics 

        456BEBDB time date stamp Tue Nov 28 155715 2006 

                0.00 version 

                     1 ordinal base 

                     2 number of functions 

                     2 number of names 


        ordinal hint RVA            name 


                    1        0 00001005 _add@8 

                    2        1 0000100A _subtract@8 


    Summary 


                7000 .data 

                1000 .idata 

                3000 .rdata 

                2000 .reloc 

                2A000 .text
 
采用下述方法可以解决上面的问题
源程序不变,我们创建一个模块定义文件,命名为dll1.def,然后添加到我们的工程中。其内容如下:
LIBRARY Dll1 


EXPORTS 

add 

subtract 

 
LIBRARY Dll1
Dump of file dll2.dll 


File Type DLL 


    Section contains the following exports for Dll2.dll 


                     0 characteristics 

        456BEECE time date stamp Tue Nov 28 160950 2006 

                0.00 version 

                     1 ordinal base 

                     2 number of functions 

                     2 number of names 


        ordinal hint RVA            name 


                    1        0 0000100A add 

                    2        1 00001005 subtract 


    Summary 


                7000 .data 

                1000 .idata 

                3000 .rdata 

                2000 .reloc 

                2A000 .text
这时发现函数名没有改变了。
本文转自jazka 51CTO博客,原文链接:http://blog.51cto.com/jazka/318878,如需转载请自行联系原作者
你可能感兴趣的文章
Laravel 技巧锦集
查看>>
Android 使用 ViewPager+RecyclerView+SmartRefreshLayout 实现顶部图片下拉视差效果
查看>>
Flutter之基础Widget
查看>>
写给0-3岁产品经理的12封信(第08篇)——产品运营能力
查看>>
ArcGIS Engine 符号自动化配置工具实现
查看>>
小程序 · 跳转带参数写法,兼容url的出错
查看>>
flutter error
查看>>
Flask框架从入门到精通之模型数据库配置(十一)
查看>>
10年重新出发
查看>>
2019年-年终总结
查看>>
聊聊elasticsearch的RoutingService
查看>>
让人抓头的Java并发(一) 轻松认识多线程
查看>>
从源码剖析useState的执行过程
查看>>
地包天如何矫正?
查看>>
中间件
查看>>
Android SharedPreferences
查看>>
css面试题
查看>>
Vue组建通信
查看>>
用CSS画一个带阴影的三角形
查看>>
前端Vue:函数式组件
查看>>