Days in DLL(一)
来源:互联网 发布:java大数据是什么 编辑:程序博客网 时间:2024/05/17 07:35
1, 静态库与动态库的区别:
最显著的区别是: 静态库 生成EXE文件后可以遗弃, 动态库却要一直跟随。
静态库的原理是: 在编译链接可执行文件(exe)时, 链接器将库中的函数与数据 与应用程序的其他模块组合起来, (这里我看作是inline 或是 insert)
动态库的原理是: 首先动态库也有类似静态库的文件(lib)(确实让人费解, 这里我们称之引入库文件, 不知大家记得函数申明吗? 所谓的申明在h文件, 实现在cpp文件?这里就是答案了。 这里的引入库文件充当的就是h文件的角色。在编译的时候跟静态库的原理相似, lib文件组合入应用程序中, 而dll仍在外部。这也是为什么生成EXE文件后动态库一直跟随的原因)
其实在上面已经道出动态链接库的优势所在。。。。(plug and play?)当我们想要更改程序里面的某一个函数的实现, easy, 只需改变其dll。还有, 这里就意味着分工合作实现的可能性, 每个人只需为自己的dll文件负责。。。更多详细内容,请百度, 这里就不多累赘了。
2, 简单制作dll && 使用之:
制作dll,
本人用的是VS2013, 新建 控制台项目 下一步 选择dll 空项目, 下面是其代码:
MyDll.cppint sharenum = 0;__declspec(dllexport) int add(int a, int b){return a + b;}__declspec(dllexport) double add(double a, double b){return a + b;}__declspec(dllexport) int minus(int a, int b){return a - b;}__declspec(dllexport) int shareNum(){return sharenum;}__declspec(dllexport) int sharenumplus(int num){sharenum += num;return shareNum();}
使用dll:
正如我上面(第一节所言, 编译需要lib 以及dll文件, 在本工程Debug中, 复制其lib dll。)下面是使用的代码:
testDll.cpp#include "stdio.h"#pragma comment (lib, "ConsoleApplication1.lib")_declspec(dllimport) int add(int a, int b);extern int minus(int a, int b);extern int shareNum();extern int sharenumplus(int num);int main(){printf("1 + 2 = %d\n", add(1, 2));printf("1 - 2 = %d\n", minus(1, 2));printf("shareNum is %d\n", shareNum());char ch;scanf("%c", &ch);printf("shareNum + 1 is %d\n", sharenumplus(1));scanf("%c", &ch);return 0;}
温馨提示:
注1: ConsoleApplication1.lib 因为我上一个工程的名称为之,这里值得注意的是 _declspec(dllimport) 与 extern (顺道说一下上文的_declspec(dllexport), 它表示该方法可以被其他程序所调用,maybe private ->>> public?), 回到正题, 这俩者的效果是一致的, 也就是声明外部调用的方法, 不同的是:_declspec(dllimport)更高效。注2:更为常见的是:头文件定义好所有函数, 源文件实现, 这里用一个技巧:
//h文件:#ifndef DLL1_API#define DLL1_API _declspec(dllimport)#endif // !DLL1_APIDLL1_API int add(int a, int b);。。。。。。//cpp:#define DLL1_API _declspec(dllexport)#include "dllHeader.h"int add(int a, int b){return a + b;}。。。
这里有个好处, 即:可以有一个类似doc的文件(h文件)可以参考,方便使用者。 当然最显著的特点是, 使用dll的时候, 只需加载lib, 函数申明可以用#include头文件解决。
#include "dllHeader.h"#include "stdio.h"#pragma comment (lib, "MyDll.lib")int main(){printf("1 + 2 = %d\n", add(1,2));char ch;scanf("%c", &ch);}
3, 从DLL中导出类:
基本格式:
//**.hclass DLL1_API robot{public :void sayhello();};//**.cppvoid robot::sayhello(){printf("hello world");}//关于DLL1_API, 请看上文温馨2
不知读者是否知道 transient, 这个是在序列化里面的(Java), 所修饰的数据将不参与序列化过程。
而这里的_declspec(export) 是否有异曲同工之妙呢? 只有用这个修饰的才能从dll 中导出。
4. 解决名字改编问题:
问题描述:
编译器在生成dll文件的时候, 会对其名字进行改编, 不同编译器, 改编的形式或许有所不同, 这就有可能发生A编译生成的dll, B不能使用的情况。
(2015/04/22 其原因是:C 中没有重载的概念,而C++有,也就是说,C++编译生成名字的时候,会加上其参数列表的内容,测试代码如下:)
//override.c#include "stdio.h"int hello(int a) { printf("arg is %d\n", a); return 0;}int hello(){ printf("no arg"); return 0;}int main() { return 0;}
结果:
插播一下(其实命名很重要,一个好的文件,函数,字段名字是无需额外的注解的,所以学好英语很重要 ovo 请忽略我,我一般百度翻译。。)
解决方法:
方法一:
//h文件:#ifndef DLL1_API#define DLL1_API <strong>extern "C" </strong>_declspec(dllimport)#endif // !DLL1_APIDLL1_API int <strong>_stdcall</strong> add(int a, int b);。。。。。。//cpp:#define DLL1_API<strong> <span style="font-family: Arial, Helvetica, sans-serif;">extern "C"</span></strong><span style="font-family: Arial, Helvetica, sans-serif;"><strong> </strong>_declspec(dllexport)</span>#include "dllHeader.h"int <strong>_stdcall</strong> add(int a, int b){return a + b;}。。。
方法二: 使用模块定义文件DEF
LIBRARY MyDllEXPORTSadd //sample1myminus= minus //sample2sample1: 表示源文件中定义的add 将以 add 符号名导出。
<strong>1 0 00011109 add = @ILT+260(_add@8)2 1 00011005 minus = @ILT+0(_minus)3 2 00011005 myminus = @ILT+0(_minus)</strong>
结语:
这里是我的一人之言, 总有疏漏, 欢迎打脸。。。
- Days in DLL(一)
- Days in Dll (二)
- in younger days
- IoT in 5 days
- days@intel(一)
- days
- Sams Teach Yourself MySQL in 21 Days
- Teach Yourself ADO.NET in 21 Days
- Sams Teach Yourself J2EE in 21 Days
- Sams Teach Yourself EJB in 21 Days
- Launching a Blog Successfully in 15 Days
- 【转】Teach yourself C++ in 21 Days.
- Prune days and Change Capture in DAC
- get days in month use javascript
- No update in recent two days!
- rest 2.5days in a week
- DLL入门(一)
- dll 学习(一)
- Android实现数据的存储技术(转)
- jsp与servlet的关系
- android 自定义Dialog背景透明及显示位置设置
- 1637 - Double Patience(状态转移+求成功概率)
- 用Python和Pygame写游戏-从入门到精通(实战二:恶搞俄罗斯方块4)
- Days in DLL(一)
- 存储过程运行日志记录通用模块
- (原创)基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集(非常好)
- HashSet中存方用户自定义数据类型数据,重写equals方法和hashCode方法
- POJ-1236(有向图强连通分量 + 缩点 + 加边使得整个图强连通)
- windows批处理在androi开发中的作用
- MySQL执行计划解读
- instanceof用法
- 用Python和Pygame写游戏-从入门到精通(实战三:植物大战僵尸1)