我需要将一些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
答案 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);
}
我不确定从 < / p>
@<number>
文件中剥离.def
部分是否正确,我对此表示怀疑,但只是尝试一下。
在我使用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);
}