DLL导出lib文件和.h头文件

   最近工作中遇到需要调用别人的动态链接库,但是只有个dll文件,别的一概没有,这可怎么办呢。还有不少dll导出的都是类,直接显式调用不太方便,最后综合网上的办法,自己再写两个工具,终于实现了将dll导出lib文件,并同时生成.h头文件。
    
    还是自己动手才能丰衣足食啊。

=========================================================================

问题:如果手上只有一个DLL文件,没有lib文件.h头文件,程序里怎么调用它

方法当然很简单,
先用VC的工具Depends.exe查看导出函数的函数名啊
用IDAPro或者其他反汇编工具分析函数原型
再用API函数:LoadLibrary,GetProcAddress
完成!

但是……如果Dll导出的是一个个的类呢,这就稍微有点麻烦

========================================================================

方法1:还是用显式调用,LoadLibrary,GetProcAddress,
这时候就要在头文件里声明一个个的“类成员函数的函数指针”了,
把GetProcAddress返回值赋给这些指针,使用时调用指针即可。

如何知道类的成员函数原型是长什么样的呢?
还是Depends工具,如果直接看,会发现导出函数名中有好多"?","@"等符号,

Depends的上面有个按钮"C++"(如果没有这个按钮,说明你的Depends太老了,下载个新的吧),点了这个按钮,再看看函数名有啥变化,是不是变得比较好理解了
不过Depends解析得还不够完全,看不出来成员函数是public、protected还是private,也不知道调用约定是__cdecl、__stdcall还是__fastcall,是虚函数还是静态成员函数。
如果要知道这些,还是用VC的undname.exe看得比较全面。

=======================================================================

方法2:用lib文件进行隐式链接,这样无需LoadLibrary,个人感觉比较方便的
如何生成lib文件呢,假设动态链接库名为example.dll,步骤如下

1、执行dumpbin.exe/EXPORTS example.dll>example.def
生成了一个def文件,里面的内容大概是下面这样:
   ordinal hint RVA      name
       1    0 00004570?function1@@
       2    1 00004540?function2@@

2、编辑这个def文件,删掉没用的信息,将它整理成这样的格式 :
        LIBRARY "example"
        EXPORTS
        ?function1@@    @1
        ?function2@@    @2
上面的@1和@2是根据第1个步骤中的ordinal序号来的

这个步骤我写了个程序HandleDef.exe来自动修改,否则太多函数的话手动改就累死了

3、运行lib.exe/def:example.def
生成了example.lib和example.exp文件。这个lib文件就可以在VC里用了,
比如这样    #pragma comment(lib,"example.lib")

4、新建一个文件example.tmp,里面保存函数名
?function1@@
?function2@@
然后运行undname.exeexample.tmp>example.txt
这样函数名就解析到example.txt文件里了

5、自己写了个HandleTxt.exe程序,把example.txt转换为example.h
转换后变成类似下面这样:

1.       class __declspec(dllimport) CExample  

2.       {  

3.       public: int function1(void);  

4.       public: void function2(char);  

5.       };  

这个样子的基本就能直接拷到VC里用了。
不过,如果自己的程序要用到构造函数来新建一个对象的话,对导入类进行声明的时候要事先分析好类对象的内存分布(这可不是个简单的事啊),上面这个CExample类应该这样声明

1.       class __declspec(dllimport) CExample  

2.       {  

3.       public: int function1(void);  

4.       public: void function2(char);  

5.       public: BYTE m_data[256];  

6.       };  

//上面m_data具体多少个字节,要靠自己反汇编分析,没法自动生成,具体方法比较麻烦,有兴趣的可以去网上查一些C++类的反汇编资料。

==========================================
总结:
为了方便,把以下内容写到一个批处理文件中
set name=example

dumpbin.exe/EXPORTS %name%.dll>%name%.def
HandleDef.exe %name%.def
lib.exe /def:%name%.def /MACHINE:IX86
undname.exe %name%.tmp>%name%.txt
HandleTxt.exe %name%.txt

执行完之后生成lib文件和h文件。
=========================================

上面提到的HandleDef.exe和HandleTxt.exe是我自己用C#写的小程序。

写了这么多,也不知道有没有人会感兴趣。

注:我这个还只是适用于VC编写的dll导出的类

如果用extern"c"导出的函数,除了自己反汇编分析原型,貌似没有别的办法

如何调用非VC编译器编译出来的类,暂时未研究过。


 

下载地址:http://pan.baidu.com/netdisk/singlepublic?fid=795627_2574562052

 

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
使用VS2015编译和调用动态链接库dll 1. 首先建工程,选择dll,记得勾上“导出符号” 后面不用自己搞那些宏定义会省事很多。 建立工程myDll,记得勾上“导出符号” 类型选择dll 2. IDE自动生成的代码已经把整个架构弄好了,其中和项目同名的.h和.cpp文件就是我们自己写代码的地方了。我想写的dll导出一个类,在这里我就直接在它自动生成的CmyDll类上面改了。 myDll.h myDll.cpp 在mydll.h和mydll.cpp中给类添加成员函数 //mydll.h class MYDLL_API CmyDll { public: CmyDll(void); // TODO: 在此添加您的方法。 int myFunction(int a, int b); }; //mydll.cpp int CmyDll::myFunction(int a, int b) { return a*b; } 3.编译的时候我选择了release,这里可以用默认的debug也行 在mydll.h和mydll.cpp中给类添加成员函数 最后生成解决方案后产生的mydll.lib和mydll.dll就是我们需要的二进制文件了。lib文件是编译是要用的,而dll是调用这个库的程序运行时需要的。 调用dll 1.重新建立一个工程 这回选择普通的控制台程序就行了。我建了个名为myDllCall的工程。 2.把库的头文件include进来,以及连接lib文件 其中 include进来的 myDll.h 和 **#pragma comment()**的lib根据自己的路径写。 #include "stdafx.h" #include "../../myDll/myDll/myDll.h" //头文件 #pragma comment(lib,"../../myDll/Release/myDll.lib") //调用自己写的外部库 #include int main() { CmyDll mydll; int a, b; std::cin >> a >> b; std::cout << mydll.myFunction(a, b) <> a >> b; std::cout << mydll.myFunction(a, b) << std::endl; return 0; } 3.dll放到可执行文件同一目录下面 刚刚的代码直接编译没问题,运行会报错. 直接编译没问题,运行会报错 原因是dll要和生成的可执行文件在同一个目录下,我把mydll.dll放进去之后就解决了。 我们成功的在自己的工程里调用了外部的类 可以看到我们成功的在自己的工程里调用了外部的类。
### 回答1: makeexport dll导出lib是一个非常常见的操作。一般来说,这是因为我们需要将一个动态链接库中的函数导出到一个静态链接库中,以供其他代码使用。这个过程需要使用一些工具,主要有两个,分别是makeexports和lib。 首先,我们需要使用makeexports工具来生成一个.def文件,该文件列出了我们想要导出的函数和它们在库中的名称。然后,我们可以使用lib工具将这些导出函数生成为一个静态链接库。这个过程确保了我们可以使用这些函数而不需要动态加载它们。 makeexports工具lib工具都是微软Visual Studio开发环境自带的工具,可以在命令行中使用。如果你使用的是其他编译器或开发环境,则可以使用类似的工具来实现相同的目的。 总的来说,将动态链接库导出为静态链接库是一个重要的操作,使我们可以将函数共享给其他代码而不需要它们运行时被动态加载。 ### 回答2: makeexport是一个工具,用于从动态链接库(DLL)中导出函数。这个工具可以通过在命令行中指定DLL导出函数列表来生成一个LIB文件,这个LIB文件包含DLL导出函数的符号和地址信息,以便在链接期间使用。 如果你需要使用某个DLL中的函数,但是没有相应的头文件LIB文件,那么你可以使用makeexport工具来生成一个LIB文件。具体操作步骤如下: 1. 下载makeexport工具; 2. 在命令行中运行makeexport,并指定需要生成LIB文件DLL以及导出函数列表; 3. 执行完命令后,会在当前目录下生成一个LIB文件; 4. 将LIB文件添加到你的项目中,以便在链接期间使用。 需要注意的是,使用makeexport工具生成的LIB文件只包含DLL中指定的导出函数。如果你需要使用DLL中其他的函数,你需要使用其他工具或手动编写相应的头文件LIB文件。 总的来说,使用makeexport工具来生成LIB文件可以方便地使用DLL中的函数,但是需要注意生成的LIB文件不一定包含所有函数信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值