编写兼容的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替换按顺序和名称导出两者的主要内容,如果未能解决你的问题,请参考以下文章

我可以更改 dll 的名称以在运行时加载吗?

QT 调用VS2015编写的Dll

win7出现故障模块kernelbase.dll

怎么打开和修改dll文件的?如何调用和编辑

怎么打开和修改dll文件的?如何调用和编辑

C++ 中的 DLL 导出调用,带有“::”字符串名称