编写兼容的DLL替换按顺序和名称导出两者
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编写兼容的DLL替换按顺序和名称导出两者相关的知识,希望对你有一定的参考价值。
我正在编写克隆DLL,并且需要将它们替换为已经链接的程序。我不希望通过序数强制导入与我的替换DLL / .Lib链接的程序;但是,我确实希望已经链接到原始DLL的程序能够按顺序导入,而不是被我的替换破坏。 - 因此,我需要按名称导出我的函数,但保留序数的映射。
我怎样才能做到这一点?
如果我像这样创建一个.def文件(Interface.def):
LIBRARY Interface
EXPORTS
??0Interface@@QAE@ABV0@@Z @1
??0Interface@@QAE@XZ @2
??1Interface@@MAE@XZ @3
??4Interface@@QAEAAV0@ABV0@@Z @4
??_7Interface@@6B@ @5
?bIsBluetoothAddress@Interface@@SA_NABV?$CStringT@DV?$StrTraitMFC_DLL@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@@Z @6
?bIsUSBAddress@Interface@@SA_NABV?$CStringT@DV?$StrTraitMFC_DLL@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@@Z @7
?bIsWiFiAddress@Interface@@SA_NABV?$CStringT@DV?$StrTraitMFC_DLL@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@@Z @8
?getBluetoothAddressFromResource@Interface@@SAXABV?$CStringT@DV?$StrTraitMFC_DLL@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@AAV23@@Z @9
?getFantomLoadStatus@Interface@@SA?AW4TFantomLoadStatus@@XZ @10
?getFriendlyNameFromResourceString@Interface@@SA_NABV?$CStringT@DV?$StrTraitMFC_DLL@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@AAV23@@Z @11
?pzSambaAddress@Interface@@2PBDB @12
allocateNxtInterface @13
bIsExecutableFileType @14
bIsPairedBluetoothName @15
destroyInterface @16
并且,在Interface.h的头文件中,我确保放置:
#ifndef __INTERFACE_H__
#ifndef __INTERFACE_EXPORT__
#define __INTERFACE_EXPORT__ __declspec( dllimport )
#endif
class __INTERFACE_EXPORT__ Interface { /* definitions omitted in this example. */
}
extern "C" {
Interface* allocateInterface( void );
void destroyInterface( Interface * );
bool bIsExecutableFileType( Interface * );
bool bIsPairedBluetoothName( Interface * );
}
但是,即便如此 - 当我在Visual Studios 2008(版本9)下使用它时,任何链接到它创建的.Lib的程序都会严格按顺序导入 - 这不是我想要的。我认为.def中需要NONAME才能获得不良行为 - 但即使没有切换,它也会发生...(参见上面的.def文件)
这是我如何构建dll,并将测试程序作为命令行的批处理文件....
cl /nologo /Zi /EHsc /c Interface.cpp
rem TO make the .def file from the original .dll, with closest mangled names in obj file.
rem uncomment this line: python dll2def.py Interface.obj InterfaceA.dll
link /nologo /debug /DLL /def:Interface.def Interface.obj /NODEFAULTLIB:LIBCMT msvcrt.lib user32.lib atls.lib
cl /nologo /Zi /EHsc /c test.cpp
link /nologo /debug /map /mapinfo:exports test.obj Interface.lib
然而,在我运行了上面显示的buld.bat脚本后,test.exe显示了序数:这不是我想要的。
dumpbin.exe /进口
Dump of file test.exe
File Type: EXECUTABLE IMAGE
Section contains the following imports:
Interface.dll
4303E0 Import Address Table
4301F4 Import Name Table
0 time date stamp
0 Index of first forwarder reference
Ordinal 13
Ordinal 12
KERNEL32.dll
430228 Import Address Table
43003C Import Name Table
0 time date stamp
0 Index of first forwarder reference
266 GetTickCount
3D0 SetEnvironmentVariableA
55 CompareStringW
D9 EnterCriticalSection
...
那么:即使有序数可用,我如何明确地获取cl.exe或链接以使用NAME?
您的.def文件通过name和ordinal导出函数。这是你想要的DLL。因此,生成的DLL是您想要的。
问题出在生成的.lib文件中。工具链创建一个.lib文件,该文件更喜欢按顺序而不是名称导入。这并非不合理,因为这样做会更快。如果选择按顺序或名称导入,则选择更有效的导入。
因此,您的解决方案是负责创建.lib文件。在主构建之后直接调用lib,并将其传递给修改后的.def文件。使用lib的/ def选项。修改后的.def文件删除了序数。这是您在将新代码链接到库时要使用的.lib文件的版本。
以上是关于编写兼容的DLL替换按顺序和名称导出两者的主要内容,如果未能解决你的问题,请参考以下文章