我在VS2008中有一个x64项目,需要包含几年前用Fortran编写的旧版本库。我没有源代码,无法重新编译它。 .lib中的函数名称前缀为下划线,但x64项目仅使用不想识别stdcall或cdecl引用的fastcall引用。是否有任何东西可以告诉构建器识别带有前置下划线的名称?
所有有争议的问题,因为一旦我通过命名问题,它最终告诉我致命错误LNK1112:模块机器类型x86与目标机器类型x64冲突,所以无论如何我无法链接这个旧库。
答案 0 :(得分:3)
带有前置下划线的名称由C链接使用,因此如果您的实现语言是C ++(是吗?),则应使用此声明
extern "C" {
int foo();
float bar();
}
它也应该使用__cdecl,虽然我不确定。
答案 1 :(得分:3)
我假设您的旧版库是32位。您是否尝试将项目编译为x86而不是x64,以查看问题是否来自x64编译?如果是这种情况,你可以尝试这里的东西:
答案 2 :(得分:3)
你肯定需要头文件。 如果仍有问题,则表示标题中的定义未指定调用约定。
处理linke错误的一般方法:
转储应用程序使用的函数
dumpbin / symbols
转储库和dll
dumpbin / exports dumpbin / exports
对于静态库
dumpbin /symbols <libraryFileName.lib>
在2个转储中找到函数名称(3个用于dll +导入库) 并确保它们完全相同。
您找到的任何不匹配都会表明您的问题是什么
将您的通话更改为与导出的内容相同的结果
解释(部分)结果:
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&gt; dumpResult.txt
奖金提示:有时在一个转储中你会看到未签名的短片和 在另一个wchar_t 这意味着编译不是使用相同的设置完成的 对于wchar_t(原生类型与否)
答案 3 :(得分:1)
您的x64项目是什么语言?您应该能够在函数的extern定义中指定调用约定:
extern int __stdcall foo();
答案 4 :(得分:0)
你多年前提到Fortran,很可能是32位。名称修改(前导下划线)是冰山的一角,即使你设法修复它(调用约定问题),你仍然有从32位调用64位的问题。上面的Ben Robbins的链接可能有所帮助。我们有一个类似的问题,我们认为也许我们能够将我们的32位DLL包装在COM包装器中,然后从64位调用COM包装器。不知道这是否有效,因为我们最终找到了源代码并获得了良好的64位编译。