链接到没有.lib的.dll文件

时间:2017-07-11 09:36:34

标签: c dll name-mangling

我需要将一些Delphi代码重写为C ++,我们需要链接到动态库TMLComm2004.dll。事实证明,我们没有任何.lib文件,所以我们决定使用以下命令行生成它:

dumpbin /EXPORTS C:\Users\fayard\Desktop\TMLComm2004.dll > C:\Users\fayard\Desktop\TMLComm2004.txt

我们获得以下文件

Microsoft (R) COFF/PE Dumper Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file C:\Users\fayard\Desktop\TMLComm2004.dll

File Type: DLL

  Section contains the following exports for TMLcomm.dll

    00000000 characteristics
    401F6AD5 time date stamp Tue Feb  3 10:33:09 2004
        0.00 version
          1 ordinal base
          27 number of functions
          27 number of names

    ordinal hint RVA      name

          1    0 00001122 _MSK_COFFDownloadFlash@16
          2    1 0000114F _MSK_COFFDownloadRAM@20
          3    2 0000106E _MSK_CheckSum@12
          4    3 00001172 _MSK_CloseComm@0
          5    4 00001190 _MSK_GetActiveBoard@4
          6    5 0000109B _MSK_GetBoardInfo@8
          7    6 0000104B _MSK_GetBytesCountInQueue@0
          8    7 0000119A _MSK_GetChar@4
          9    8 000010E6 _MSK_GetCharNoWait@4
         10    9 000011A4 _MSK_GetCommBaudRate@4
         11    A 000010DC _MSK_GetHostBoard@4
         12    B 0000108C _MSK_OpenComm@16
         13    C 000011DB _MSK_ReceiveData@16
         14    D 000011CC _MSK_ReceiveMessage@4
         15    E 0000105A _MSK_RegisterReceiveUnsolicitedMsgHandler@4
         16    F 000011AE _MSK_ResetMSKBoard@0
         17   10 00001037 _MSK_SendChar@4
         18   11 000010EB _MSK_SendData@16
         19   12 0000126C _MSK_SendMessage@4
         20   13 0000128F _MSK_SetActiveBoard@4
         21   14 00001136 _MSK_SetB0BlockAsData@4
         22   15 0000100A _MSK_SetBoardBaudRate@4
         23   16 00001019 _MSK_SetCharMode@4
         24   17 00001168 _MSK_SetCommBaudRate@4
         25   18 00001050 _MSK_SetDebugWindow@8
         26   19 00001276 _MSK_SetHostBoard@4
         27   1A 00001046 _MSK_UpdateCommTimeouts@0

  Summary

        C000 .data
        3000 .idata
        6000 .rdata
        4000 .reloc
       21000 .rsrc
       3E000 .text
        2000 shdata

然后,我们编辑了TMLComm2014.txt文件,并将其更改为.def文件并删除了@xx。该文件看起来像:

EXPORTS
_MSK_COFFDownloadFlash
...

然后,我们生成一个.lib文件:

lib /def:C:\Users\fayard\Desktop\TMLComm2004.def /out:C:\Users\fayard\Desktop\TMLComm2004.lib

我们编译以下程序:

extern "C" {
  bool MSK_OpenComm(unsigned char a, unsigned short b, bool c, unsigned char d);
}

...

当我们编译并链接.lib时,我们收到错误:

LNK2019 unresolved external symbol _MSK_OpenComm referenced in function...

我做错了什么?

更新

我已经设法编译:

extern "C" {
  bool __stdcall MSK_OpenComm(unsigned char a, unsigned short b, bool c, unsigned char d);
}

但现在问题出在链接时。我从命令行感到困惑,我有:

==================================================
dumpbin /headers TMLComm.lib

  Version      : 0
  Machine      : 14C (x86)
  TimeDateStamp: 5964C365 Tue Jul 11 14:24:05 2017
  SizeOfData   : 00000022
  DLL name     : TMLComm2004.dll
  Symbol name  : __MSK_OpenComm@16
  Type         : code
  Name type    : no prefix
  Hint         : 11
  Name         : _MSK_OpenComm@16

==================================================
dumpbin /exports TMLComm.dll

         12    B 0000108C _MSK_OpenComm@16

==================================================

编译现在很好,但问题出在链接时:

link tmlcomm.obj Motor.obj main.obj TMLComm.lib /out:main.exe


Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.

tmlcomm.obj : error LNK2019: unresolved external symbol _MSK_OpenComm@16 referenced in function "bool __cdecl msk_opencomm(unsigned char,unsigned short,bool,unsigned char)" (?msk_opencomm@@YA_NEG_NE@Z)
Teclis.exe : fatal error LNK1120: 1 unresolved externals

1 个答案:

答案 0 :(得分:0)

看看微软的documentation of decorated names。对于C,前导下划线和尾随@<number>表示stdcall调用约定,它与标准cdecl不同。

因此,您应该修改符号以@<number>结尾的所有函数的声明:

extern "C" {
  __stdcall bool MSK_OpenComm(unsigned char a, unsigned short b, bool c, unsigned char d);
}

我不确定从@<number>文件中剥离.def部分是否正确,我对此表示怀疑,但只是尝试一下。 < / p>

在我使用MinGW工具创建.def文件(gendef)的实验中,.def中的名称包含在内领先的下划线,但在最后包含@<number>部分。因此,对于此示例函数,.def应具有以下行:

MSK_OpenComm@16

手动创建这些必需文件的替代方法是MinGW附带的工具。您可以执行以下操作:

gendef foobar.dll                     # generates the .def
dlltool -d foobar.def -l foobar.lib   # generates the import library

根据您的评论,可能需要手动修改.def文件gendef,以便您包含以下内容:

MSK_OpenComm@16=_MSK_OpenComm@16

似乎gendef可能会混淆,因为dll会导出装饰名称,这是不期望的。

使用导入库时,这将具有“静态存根”,其名称类似于DLL的实际导出符号,但前缀为__imp__。为了解决这个问题,您需要在声明中使用另一个属性:

extern "C" {
  __declspec(dllimport) __stdcall bool MSK_OpenComm(unsigned char a, unsigned short b, bool c, unsigned char d);
}