3

我在 VS2008 中有一个 x64 项目,需要包含一个多年前用 Fortran 编写的旧遗留库。我没有源代码,无法重新编译。.lib 中的函数名称前加下划线,但 x64 项目仅使用不想识别 stdcall 或 cdecl 引用的 fastcall 引用。有什么可以告诉构建识别带有前置下划线的名称吗?

编辑

自从我解决了命名问题后,所有的争论点最终告诉我致命错误 LNK1112:模块机器类型 x86 与目标机器类型 x64 冲突,所以无论如何我都无法链接这个旧库。

4

5 回答 5

4

C 链接使用带有前置下划线的名称,因此如果您的实现语言是 C++(是吗?),您应该使用此声明

extern "C" {
  int foo();
  float bar();
}

它也应该使用 __cdecl,尽管我不确定。

于 2009-02-11T00:26:28.287 回答
3

我假设您的旧库是 32 位的。您是否尝试过将项目编译为 x86 而不是 x64 以查看问题是否来自 x64 编译?如果是这样的话,你可以试试这里的东西:

从 64 位进程调用 32 位代码

于 2009-02-11T01:10:00.037 回答
3

你肯定需要头文件。如果您仍然有问题,则表示标头中的定义未指定调用约定。

处理链接错误的一般方法:

  1. 转储应用程序使用的函数

    垃圾箱/符号

  2. 转储库和 dll

    垃圾箱 / 出口 垃圾箱 / 出口

对于静态库

dumpbin /symbols <libraryFileName.lib>
  1. 在 2 个转储中找到函数名称(3 个用于 dll+import 库)并确保它们相同。

  2. 您发现的任何不匹配都将表明您的问题是什么

  3. 更改您的调用以得到与导出的内容相同的结果


解释(部分)结果:

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 的相同设置(是否为原生类型)

于 2009-02-11T09:36:22.677 回答
1

您的 x64 项目使用什么语言?您应该能够在函数的外部定义中指定调用约定:

  extern int __stdcall foo();
于 2009-02-10T20:44:49.193 回答
0

您在几年前提到了 Fortran,它很有可能是 32 位的。名称修改(前导下划线)是冰山一角,即使你设法解决了这个问题(调用约定问题),你仍然会遇到从 32 位调用 64 位的问题。上面 Ben Robbins 的链接可能会有所帮助。我们有一个类似的问题,我们认为也许我们能够将我们的 32 位 DLL 包装在 COM 包装器中,然后从 64 位调用 COM 包装器。不知道这是否可行,因为我们最终找到了源代码并获得了良好的 64 位编译。

于 2009-02-11T02:15:12.673 回答