由于我们经常要调用一些第三方厂商或其他编译器编写的动态链接库,但是一般都不提供源文件或.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 动态链接库实现文件
编译器产生如下错误:
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;
}
|