链接到不带.lib的.dll文件 [英] Linking to a .dll file without the .lib
问题描述
我需要将一些Delphi代码重写为C ++,并且需要链接到动态库 TMLComm2004.dll
.事实证明,我们没有任何 .lib
文件,因此我们决定使用以下命令行生成该文件:
dumpbin/EXPORTS C:\ Users \ fayard \ Desktop \ TMLComm2004.dll>C:\ Users \ fayard \ Desktop \ TMLComm2004.txt
我们获得以下文件
Microsoft(R)COFF/PE Dumper版本14.00.24215.1版权所有(C)Microsoft Corporation.版权所有.文件C:\ Users \ fayard \ Desktop \ TMLComm2004.dll的转储档案类型:DLL本节包含TMLcomm.dll的以下导出00000000特征401F6AD5时间日期戳2004年2月3日星期二10:33:090.00版本1个序数基数27种功能27个名字顺序提示RVA名称1 0 00001122 _MSK_COFFDownloadFlash @ 162 1 0000114F _MSK_COFF下载RAM @ 203 2 0000106E _MSK_CheckSum @ 124 3 00001172 _MSK_CloseComm @ 05 4 00001190 _MSK_GetActiveBoard @ 46 5 0000109B _MSK_GetBoardInfo @ 87 6 0000104B _MSK_GetBytesCountInQueue @ 08 7 0000119A _MSK_GetChar @ 49 8 000010E6 _MSK_GetCharNoWait @ 410 9 000011A4 _MSK_GetCommBaudRate @ 411个000010DC _MSK_GetHostBoard @ 412 B 0000108C _MSK_OpenComm @ 1613 C 000011DB _MSK_ReceiveData @ 1614 D 000011CC _MSK_ReceiveMessage @ 415 E 0000105A _MSK_RegisterReceiveUnsolicitedMsgHandler @ 416 F 000011AE _MSK_ResetMSKBoard @ 017 10 00001037 _MSK_SendChar @ 418 11 000010EB _MSK_SendData @ 1619 12 0000126C _MSK_SendMessage @ 420 13 0000128F _MSK_SetActiveBoard @ 421 14 00001136 _MSK_SetB0BlockAsData @ 422 15 0000100A _MSK_SetBoardBaudRate @ 423 16 00001019 _MSK_SetCharMode @ 424 17 00001168 _MSK_SetCommBaudRate @ 425 18 00001050 _MSK_SetDebugWindow @ 826 19 00001276 _MSK_SetHostBoard @ 427 1A 00001046 _MSK_UpdateCommTimeouts @ 0概括C000 .data3000 .idata6000 .rdata4000 .reloc21000 .rsrc3E000 .text2000 shdata
然后,我们编辑了 TMLComm2014.txt
文件,并将其更改为 .def
文件,并删除了@xx.该文件如下所示:
EXPORTS_MSK_COFFDownloadFlash...
然后,我们生成具有以下内容的 .lib
文件:
lib/def:C:\Users\fayard\Desktop\TMLComm2004.def/out:C:\Users\fayard\Desktop\TMLComm2004.lib
我们编译以下程序:
外部"C" {bool MSK_OpenComm(unsigned char a,unsigned short b,bool c,unsigned char d);}...
当我们编译并链接到 .lib
时,会出现错误:
LNK2019函数中引用的未解析外部符号_MSK_OpenComm ...
我怎么办?
更新
我已成功编译为:
外部"C" {布尔__stdcall MSK_OpenComm(unsigned char a,unsigned short b,bool c,unsigned char d);}
但是现在问题出在链接时.我从命令行中感到困惑,我有:
====================================================dumpbin/headers TMLComm.lib版本:0机器:14C(x86)TimeDateStamp:5964C365 2017年7月11日星期二14:24:05数据大小:00000022DLL名称:TMLComm2004.dll符号名称:__MSK_OpenComm @ 16类型:代码名称类型:无前缀提示:11名称:_MSK_OpenComm @ 16==================================================dumpbin/exports TMLComm.dll12 B 0000108C _MSK_OpenComm @ 16==================================================
现在编译正常,但问题出在链接时:
<代码>链接tmlcomm.obj Motor.obj main.obj TMLComm.lib/out:main.exeMicrosoft(R)增量链接器版本14.00.24215.1版权所有(C)Microsoft Corporation.版权所有.tmlcomm.obj:错误LNK2019:函数"bool __cdecl msk_opencomm(unsigned char,unsigned short,bool,unsigned char)"中引用的未解析的外部符号_MSK_OpenComm @ 16(?msk_opencomm @@ YA_NEG_NE @ Z)Teclis.exe:致命错误LNK1120:1个未解决的外部组件
看看Microsoft的修饰名称的文档.对于C,前导下划线和后跟 @< number>
表示 stdcall
调用约定,这与标准的 cdecl
不同./p>
因此,您应该只修改符号以 @< number>
结尾的所有函数的声明:
外部"C" {__stdcall bool MSK_OpenComm(unsigned char a,unsigned short b,bool c,unsigned char d);}
我不确定是否应该从 .def
文件中删除 @< number>
部分是否正确,我对此表示怀疑,但只需尝试一下.
通过我使用 MinGW
工具创建 .def
文件( gendef
)的工具进行的实验,该文件的名称在 .def中
应该不包括前划线,但应在末尾包含 @< number>
部分.因此,对于此示例函数, .def
应该具有以下行:
MSK_OpenComm @ 16
MinGW 附带的工具是手动创建这些必需文件的替代方法.您可以执行以下操作:
gendef foobar.dll#生成.defdlltool -d foobar.def -l foobar.lib#生成导入库
根据您的评论,您可能需要手动编辑 .def
文件 gendef
,该文件将包含以下行:/p>
MSK_OpenComm @ 16 = _MSK_OpenComm @ 16
似乎 gendef
可能会感到困惑,因为dll会导出意想不到的装饰名称.
使用导入库时,将具有静态存根"的名称,类似于DLL的实际导出符号,但带有 __ imp __
.为了解决这个问题,您需要在声明中添加另一个属性:
外部"C" {__declspec(dllimport)__stdcall bool MSK_OpenComm(无符号字符a,无符号短字符b,布尔c,无符号字符d);}
I need to rewrite some Delphi code to C++ and we need to link to the dynamic library TMLComm2004.dll
. It turns out that we don't have any .lib
file so we decided to generate it, using the following command lines:
dumpbin /EXPORTS C:\Users\fayard\Desktop\TMLComm2004.dll > C:\Users\fayard\Desktop\TMLComm2004.txt
We obtain the following file
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
Then, we have edited the TMLComm2014.txt
file and changed it to a .def
file with the @xx removed. The file looks like:
EXPORTS
_MSK_COFFDownloadFlash
...
Then, we generate a .lib
file with:
lib /def:C:\Users\fayard\Desktop\TMLComm2004.def /out:C:\Users\fayard\Desktop\TMLComm2004.lib
We compile the following program:
extern "C" {
bool MSK_OpenComm(unsigned char a, unsigned short b, bool c, unsigned char d);
}
...
When we compile and link against the .lib
, we get an error:
LNK2019 unresolved external symbol _MSK_OpenComm referenced in function...
What's wrong with what I do?
Update
I have managed to compile with:
extern "C" {
bool __stdcall MSK_OpenComm(unsigned char a, unsigned short b, bool c, unsigned char d);
}
but now the problem is at link time. I am puzzled as from command line, I have:
==================================================
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
==================================================
Compilation goes fine now, but the problem is at link time:
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
Have a look at Microsoft's documentation of decorated names. For C, a leading underscore and a trailing @<number>
denotes the stdcall
calling convention, which is different from the standard cdecl
.
So, you should just modify your declarations for all functions where the symbol ends with @<number>
:
extern "C" {
__stdcall bool MSK_OpenComm(unsigned char a, unsigned short b, bool c, unsigned char d);
}
I'm not sure whether stripping the @<number>
part from the .def
file is the right thing to do, I doubt it, but just try it out.
From my experiment with MinGW
s tool for creating a .def
file (gendef
), the name in the .def
should not include the leading underscore, but it should include the @<number>
part at the end. So for this example function, the .def
should have the following line:
MSK_OpenComm@16
An alternative to manually creating these required files are the tools that come with MinGW
. You could just do the following:
gendef foobar.dll # generates the .def
dlltool -d foobar.def -l foobar.lib # generates the import library
Based on your comments, you might need to manually edit the .def
file gendef
is giving you to contain lines like this:
MSK_OpenComm@16=_MSK_OpenComm@16
It seems that gendef
could be confused because the dll exports decorated names which isn't expected.
When using an import library, this will have "static stubs" named like the actual exported symbols of the DLL, but with __imp__
prepended. To account for this, you need yet another attribute in your declarations:
extern "C" {
__declspec(dllimport) __stdcall bool MSK_OpenComm(unsigned char a, unsigned short b, bool c, unsigned char d);
}
这篇关于链接到不带.lib的.dll文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!