隐式链接无.LIB动态链接库

原创 2002年04月08日 09:14:00
     由于我们经常要调用一些第三方厂商或其他编译器编写的动态链接库,但是一般都不提供源文件或.lib文件,而作为VC隐式链接到DLL(implicitly link to the DLL)调用,这些却是必需的。本文将主要讨论在没有源文件及.lib输入库文件或欲调用Windows未公开函数的情况下重建.Lib文件的方法。在建立之前,我们首先要了解一下DLL输出函数的几种方式。
     一、从DLL中输出函数的方式(calling conventions)
     _cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。VC将函数编译后会在函数名前面加上下划线前缀。
     _stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈。VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上"@"和参数的字节数。
     _fastcall方式的函数采用寄存器传递参数,VC将函数编译后会在函数名前面加上"@"前缀,在函数名后加上"@"和参数的字节数。
     用VC建立一个空的动态链接库,并加入以下三个文件:
     //noname.h  动态链接库头文件
     extern "C" void _stdcall  stdcallproc(void);
     extern "C" void  _cdecl cdeclproc(void);
     extern "C" void  _fastcall fastcallproc(void);
     //noname.cpp   动态链接库实现文件
     #include
     extern "C" void _stdcall  stdcallproc(void)
     { MessageBox(0,"stdcall function","dll call",0);
     }
     extern "C" void  _cdecl cdeclproc(void)
     { MessageBox(0,"cdecl function ","dll call",0);
     }
     extern "C" void  _fastcall fastcallproc(void)
     { MessageBox(0,"fastcall function ","dll call",0);
     }
     //noname.def  动态链接库输出函数定义
     LIBRARY      "noname"
     EXPORTS
     stdcallproc @1 noname
     cdeclproc  @2
     fastcallproc @3
     编译后生成noname.lib,输出函数_cdeclproc,_stdcallproc@0,@fastcallproc@0;生成的noname.dll在Exescope等PE格式的工具中只能看到cdeclproc和fastcallproc函数,因为stdcallproc被指定noname属性,没有名字输出,类似于Windows未公开函数。
     二、可执行程序调用DLL的方式
     可执行程序可以采用隐式链接(implicit linking)或显式链接(explicit linking)两种方式调用一个DLL。
     使用显式链接时,使用DLL的程序在使用之前必须加载(LoadLibrary)加载DLL从而得到一个DLL模块的句柄,然后调用GetProcAddress函数得到输出函数的指针,在退出之前必须卸载DLL(FreeLibrary),因为不是本文重点,具体例程请参考有关文档。显然,在调用大量的函数时这种方法会很不方便。
     使用隐式链接时,可执行程序链接到一个包含DLL输出函数信息的输入库文件(.LIB文件)。操作系统在加载使用可执行程序时加载DLL。可执行程序直接通过函数名调用DLL的输出函数,调用方法和程序内部其他的函数是一样的。
     三、重建.Lib输入库文件
     根据微软的建议,要想隐式地链接到一个DLL,可执行程序必须从DLL的提供者那儿得到一个包含输出函数的头文件(.h文件)、一个用于链接的输入库(.lib文件)。愿望是很好的,但是一般情况下,我们都无法得到第三方动态链接库的输入库文件,或者我们需要调用Windows未公开函数。如果你是使用Delphi或Visual Basic开发程序,那么,你只要简单的申明一下函数和输出库就可以了。但是,使用VC的朋友们只好重建.Lib文件了。
     1.删掉第一步中生成的noname.lib(假设我们没有这个文件)。
     2.用微软的DumpBin.exe:dumpbin /exports noname.dll>noname.def,留下noname.def文件的输出段:
         ordinal hint RVA      name
               2    0 00001005 cdeclproc
               3    1 0000100F fastcallproc
               1      0000100A [NONAME]
     修改为:
     LIBRARY      "noname"
     EXPORTS
     cdeclproc    @2
     fastcallproc @3
     nonameproc   @1 //请注意与第一步中noname.def的区别:nonameproc可以自己指定为任何名字
     再执行lib.exe /def:noname.def即可生成noname.lib文件(但如果这个动态链接库不仅仅包含_cdecl类型函数,那么这个noname.lib还不是最终可用的.lib文件,具体请看下文)。
     3.建立一个名为DllCaller的Win32控制台程序,将刚才生成的noname.dll和noname.lib拷入DllCallerdebug目录。
     //DllCaller.cpp
     //声明函数原型
     extern "C" void _stdcall  nonameproc(void);
     extern "C" void  _cdecl cdeclproc(void);
     extern "C" void  _fastcall fastcallproc(void);
     //链接输入库文件
     #pragma comment(lib,"debug/noname.lib")
     int main(int argc, char* argv[])
     {
         nonameproc();
         cdeclproc();
         fastcallproc();
         return 0;
     }
     编译器产生如下错误:
     DllCaller.obj : error LNK2001: unresolved external symbol @fastcallproc@0
     DllCaller.obj : error LNK2001: unresolved external symbol _nonameproc@0
     根据错误提示信息将noname.def更改如下:
     @fastcallproc@0 @3
     nonameproc@0 @1
     重新生成noname.lib,即可重新编译DllCaller.exe。
     四、调用Windows未公开函数
     根据以上分析,下面给出一个简单的调用Window98系统Shell32.DLL中序号为60的未公开函数,执行后将出现重新启动的对话框。
     //shell32.def,据此生成Shell32.LIB
     LIBRARY      "shell32"
     EXPORTS
     SHShutDownDialog@4 @60
    
     // DllCaller.cpp:调用未公开函数的控制台程序
     //函数声明
     extern "C" long  _stdcall SHShutDownDialog(long lShutdown);
     //链接输入库文件
     #pragma comment(lib,"debug/shell32.lib")
     int main(int argc,char* argv[])
     {
        SHShutDownDialog(0);
     return 0;
     }
     本文所有程序在VC6.0,Windows98SE环境下调试通过,也希望这些程序对于用VC的朋友有所帮助。

静态库、动态库,dll文件、lib文件,隐式链接、显式链接浅见

静态链接、动态链接 静态库和动态库分别应用在静态链接方式和动态链接方式中,所谓静态链接方式是指在程序执行之前完成所有的链接工作,把静态库一起打包合入,生成一个可执行的目标文件(EXE文件...
  • dcrmg
  • dcrmg
  • 2016年12月01日 23:10
  • 864

VC中隐式链接无.LIB动态链接库的方法

 摘要:     本文提出在不具备动态链接库的源文件或.   Lib输入库文件或欲调用Windows未公开函数的情况下重建.Lib文件的方法,并给出相应的例子。         关键词:未公开函数  ...
  • iiprogram
  • iiprogram
  • 2007年01月31日 09:19
  • 840

动态链接库基础-隐式链接与显式链接

静态链接库(*.lib) 如果在程序中使用静态链接库,那么编译器在链接的过程中会将*.obj文件和*.lib文件组织成可执行exe文件,也就是将.lib中的代码链接到可执行文件中,因此生成的exe文...
  • Hilavergil
  • Hilavergil
  • 2017年11月15日 20:53
  • 110

dll显式和隐式链接原理

应用程序导入函数与DLL文件中的导出函数进行链接有两种方式:隐式链接和显式链接。所谓的隐式链接是指在应用程序中不需指明DLL文件的实际存储路径,程序员不需关心DLL文件的实际装载。而显式链接与此相反。...
  • lostlander
  • lostlander
  • 2005年12月26日 10:56
  • 4046

动态链接库DLL的加载:隐式加载(载入时加载)和显式加载(运行时加载)

静态链接库在链接时,编译器会将 .obj 文件和 .LIB 文件组织成一个 .exe 文件,程序运行时,将全部数据加载到内存。 如果程序体积较大,功能较为复杂,那么加载到内存中的时间就会比较长,最...
  • u010154760
  • u010154760
  • 2015年05月13日 10:23
  • 2803

C++ 多个类的DLL封装以及隐式链接和显式链接2种方法调用

将OpenCL和OpenCV一些简单的方法封装成DLL,具体OpenCL和OpenCV的配置方法可以参考本人的博客。 VS2015下安装与编译OpenCV源码并在VS2015下配置OpenCV环境 ...
  • waterbinbin
  • waterbinbin
  • 2016年09月22日 18:02
  • 1921

g++ 编译动态链接库和静态链接库

现在我有hello1.cpp和hello2.cpp两个文件,现在我要生成动态链接库libhello.so和静态链接库libhello.a。以下为步骤: 1.生成动态链接库: g++ -m32 hel...
  • dqjyong
  • dqjyong
  • 2014年03月25日 19:20
  • 14393

在VC++中隐式调用动态链接库

这里主要讨论在一般的VC工程中如何调用用VC创建的动态链接库,主要涉及到编译环境的设置。例如:已经用VC的Win32 Dynamic-Link Liberary向导创建了一个动态链接库项目,现在需要在...
  • univer1
  • univer1
  • 2005年07月12日 20:20
  • 1267

cmake 链接动态链接库

使用相对路径的时候,你要让cmake能够搜索到找到你动态库,就像直接使用gcc/g++来链接的时候一样,要使用-L来指定第三方库所在路径。 cmake可以使用 LINK_DIRECTORIES 命令...
  • mengfanteng
  • mengfanteng
  • 2015年01月22日 14:10
  • 2531

静态链接库(lib)和动态链接库(dll)的区别和使用

一,概念         1)静态链接库就是你使用的.lib文件,库中得代码最后需要连接到你的可执行文件中去,所以静态连接的可执行文件一般比较大一些。          使用方法    1>  ...
  • zang141588761
  • zang141588761
  • 2016年01月12日 09:53
  • 4189
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:隐式链接无.LIB动态链接库
举报原因:
原因补充:

(最多只允许输入30个字)