1

我正在编写克隆 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 显示序数:这不是我想要的。

转储bin.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 或链接以使用名称?

4

1 回答 1

1

您的 .def 文件按名称和序号导出函数。这就是您想要的 DLL。因此,生成的 DLL 如您所愿。

问题出在生成的 .lib 文件中。工具链创建一个 .lib 文件,该文件更喜欢按序号而不是名称导入。这并非不合理,因为这样做更快。考虑到按序号或名称导入的选择,它会选择更有效的那个。

因此,您的解决方案是负责创建 .lib 文件。在主构建之后直接调用 lib,并将修改后的 .def 文件传递​​给它。使用 lib 的 /def 选项。修改后的 .def 文件删除了序数。这是您在将新代码链接到库时希望使用的 .lib 文件版本。

于 2013-12-16T21:09:32.673 回答