关于自行编译动态库的坑

关于创建lzma(压缩、解压)动态库的坑

使用错误的dll时的现象:

最开始只将lzma.dll放到了debug文件夹下,在qt中使用Qlibrary类调用dll库。

Qlib.setFileName(strDllPath); Qlib.load();load时是可以通过的,显示已加载。但是运行下一步Qlib.resolve();显示QString::arg:argument missing ***; 就是乱码了。然后在向下运行就会触发断点显示0X000000。函数并没有被调用。经查询触发的这个断点就是缺库或者是库不对。

然后用记事本打开这个错误的DLL,搜索函数接口lzma_en和 lzma_de都是搜不到的,正常情况下是可以搜到的,这就是为什么load时显示正确,而resolve时显示乱码。

对外的函数接口:解压lzma_de(); 压缩lzma_en();

编译静态库时lzma.h文件内容:

extern  “C”{

//回调函数

Typedef int (_stdcall * lzma_enProcessCallBack)(unsigned long ,  unsigned long , void *);

Typedef int (_stdcall * lzma_deProcessCallBack)(unsigned long ,  unsigned long , void *);

//函数接口

 int lzma_en(char*, char* , lzma_enProcessCallBack , void*);

 int lzma_de(char*, char* , lzma_deProcessCallBack , void*);

}

Extern “C” 的作用:当你的dll是使用C语言编写,而你要将它使用到C++中时,需要带有这个关键词。

当我使用以上内容去编译.dll的时候,debug/release文件夹下只生成了lzma.dll、lzma.ilk、lzma.pdb等这些文件。

如果将lzma.h的内容改成

__declspec(dllexport)  int  lzma_en(char*, char* , lzma_enProcessCallBack , void*);

__declspec(dllexport)  int  lzma_de(char*, char* , lzma_deProcessCallBack , void*);

编译时就会产生lzma.lib和lzma.exp这两个库文件。编译时输出:正在创建库***/Debug/*.lib和对象***/Debug/*.exp

工程中,其他地方调用dll时,工程路径下有.dll、.lib、.ilk、.pdb、.exp这5个文件。但是使用错的文件编出来的就不会产生.lib和.exp这两个文件。

(我在查关于编译dll的资料时,就发现不止一篇文章提到了.lib,我自己还很纳闷,我编译后,并没有产生.lib)

在编译动态库或者是静态库的时候,可以选择是Release/Debug。Release就是经过优化过后的版本,着重于性能优化和减少程序体积。Debug下编译器不会对代码进行太多优化,以保留更多的调试信息。

以下参考于https://www.cnblogs.com/chixinfushui/p/9019300.html和

https://www.cnblogs.com/guojun-junguo/p/10429568.html

关于这5个文件:.dll、.lib、.ilk、.pdb、.exp

库就是包含着一堆代码和数据的东西,这个东西可以被链接程序或者可执行文件使用。库中那些可以被使用的数据和函数会被标记出来。

静态库:可以认为静态库是一堆目标文件(.obj)的集合,静态库只有lib文件,索引和实现都在其中。静态库本身就包含了实际的执行代码、符号表等。静态库和动态库都是共享代码的方式,如果采用静态库,lib中的指令会全部包含在最终生成的exe文件中。静态库中不可以再包含其他的动态库或静态库。

动态库:dll是运行时需要的。dll有两个文件引入库(.lib)和dll,引入库包含被dll导出的函数的名称和位置,dll包含实际的函数和数据,应用程序使用lib文件链接到所使用的dll文件,库中的函数和数据并不复制到可执行文件中,因此再应用程序的可执行文件中,存放的不是被调用的函数代码,而是dll所要调用的函数的内存地址,这样当一个或多个应用程序运行时再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。Dll不必被包含再最终的exe中,exe在执行时可以“动态”的引用和卸载这个与exe独立的dll文件。Dll中还可以在包含其他的动态或静态库。

.def文件(module definition file模块定义文件)是用来创建dll和对应的导出库的。在一个.def文件中,你可以指定dll将会导出哪些符号给用户使用。在默认情况下,dll内部的符号是不可见的。但是我们有方法让他们可见:a.在.def文件中使用exports语句;b.在dll源代码中使用_declspec(dllexport);c.在linker的选项中使用/EXPORT选项来导出一个函数。

现在_declspec(dllexport)使用的更多,而def文件很少使用了。

exp文件就是导出文件(export file)。如果我们现在要生成两个dll。但是这两个dll都需要调用对方的一些函数时,才会使用.exp文件。

以下内容转载于:

https://blog.csdn.net/fengbingchun/article/details/78825004

__declspec是Microsoft VC中专用的关键字,它配合着一些属性可以对标准C/C++进行扩充。__declspec关键字应该出现在声明的前面

__declspec(dllexport)用于Windows中的动态库中,声明导出函数、类、对象等供外面调用,省略给出.def文件。即将函数、类等声明为导出函数,供其它程序调用,作为动态库的对外接口函数、类等。

.def文件(模块定义文件)是包含一个或多个描述各种DLL属性的Module语句的文本文件。.def文件或__declspec(dllexport)都是将公共符号导入到应用程序或从DLL导出函数。如果不提供__declspec(dllexport)导出DLL函数,则DLL需要提供.def文件。

__declspec(dllimport)用于Windows中,从别的动态库中声明导入函数、类、对象等供本动态库或exe文件使用。当你需要使用DLL中的函数时,往往不需要显示地导入函数,编译器可自动完成。不使用__declspec(dllimport)也能正确编译代码,但使用__declspec(dllimport)使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它可以确定函数是否存在于DLL中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨DLL边界的函数调用中。声明一个导入函数,是说这个函数是从别的DLL导入。一般用于使用某个DLL的exe中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值