我在 VS2008 中有一个 x64 项目,需要包含一个多年前用 Fortran 编写的旧遗留库。我没有源代码,无法重新编译。.lib 中的函数名称前加下划线,但 x64 项目仅使用不想识别 stdcall 或 cdecl 引用的 fastcall 引用。有什么可以告诉构建识别带有前置下划线的名称吗?
编辑
自从我解决了命名问题后,所有的争论点最终告诉我致命错误 LNK1112:模块机器类型 x86 与目标机器类型 x64 冲突,所以无论如何我都无法链接这个旧库。
我在 VS2008 中有一个 x64 项目,需要包含一个多年前用 Fortran 编写的旧遗留库。我没有源代码,无法重新编译。.lib 中的函数名称前加下划线,但 x64 项目仅使用不想识别 stdcall 或 cdecl 引用的 fastcall 引用。有什么可以告诉构建识别带有前置下划线的名称吗?
自从我解决了命名问题后,所有的争论点最终告诉我致命错误 LNK1112:模块机器类型 x86 与目标机器类型 x64 冲突,所以无论如何我都无法链接这个旧库。
C 链接使用带有前置下划线的名称,因此如果您的实现语言是 C++(是吗?),您应该使用此声明
extern "C" {
int foo();
float bar();
}
它也应该使用 __cdecl,尽管我不确定。
我假设您的旧库是 32 位的。您是否尝试过将项目编译为 x86 而不是 x64 以查看问题是否来自 x64 编译?如果是这样的话,你可以试试这里的东西:
你肯定需要头文件。如果您仍然有问题,则表示标头中的定义未指定调用约定。
处理链接错误的一般方法:
转储应用程序使用的函数
垃圾箱/符号
转储库和 dll
垃圾箱 / 出口 垃圾箱 / 出口
对于静态库
dumpbin /symbols <libraryFileName.lib>
在 2 个转储中找到函数名称(3 个用于 dll+import 库)并确保它们相同。
您发现的任何不匹配都将表明您的问题是什么
更改您的调用以得到与导出的内容相同的结果
解释(部分)结果:
C函数:
_functionName = C function, __cdecl calling convention
_functionName@12 = C function, __stdcall calling convention
@functionName@12 = C function, __fastcall calling convention
(当然,数字不一定非得是12)
C++ 函数
它们看起来像 ?functionName@ 即修饰名称。但转储也包含未装饰的。
例子:
?functionName@@$$J0YMHHPADPAUKeyVal@@@Z
(extern "C" int __clrcall functionName(int,char *,struct KeyVal *))
=> you have all the info, including the fact that this is compiled to
managed code (__clrcall)
?functionName@@YAHHPADPAUKeyVal@@@Z
(int __cdecl functionName(int,char *,struct KeyVal *))
=> normal C++ function
?functionName@className@@QAEHHPADPAUKeyVal@@@Z
(public: int __thiscall className::functionName(int,char *,struct KeyVal
*))
=> member function (because of __thiscall) of the class className
等等。
提示:我建议转储到文件中,因为生成的转储可能是大的 dumpbin /exports fileToDump.lib > dumpResult.txt
额外提示:有时在一个转储中你会看到 unsigned short 而在另一个 wchar_t 这意味着编译没有使用 wchar_t 的相同设置(是否为原生类型)
您的 x64 项目使用什么语言?您应该能够在函数的外部定义中指定调用约定:
extern int __stdcall foo();
您在几年前提到了 Fortran,它很有可能是 32 位的。名称修改(前导下划线)是冰山一角,即使你设法解决了这个问题(调用约定问题),你仍然会遇到从 32 位调用 64 位的问题。上面 Ben Robbins 的链接可能会有所帮助。我们有一个类似的问题,我们认为也许我们能够将我们的 32 位 DLL 包装在 COM 包装器中,然后从 64 位调用 COM 包装器。不知道这是否可行,因为我们最终找到了源代码并获得了良好的 64 位编译。