带有下划线的未解析引用

时间:2009-02-10 20:36:44

标签: visual-studio-2008 fortran

我在VS2008中有一个x64项目,需要包含几年前用Fortran编写的旧版本库。我没有源代码,无法重新编译它。 .lib中的函数名称前缀为下划线,但x64项目仅使用不想识别stdcall或cdecl引用的fastcall引用。是否有任何东西可以告诉构建器识别带有前置下划线的名称?

修改

所有有争议的问题,因为一旦我通过命名问题,它最终告诉我致命错误LNK1112:模块机器类型x86与目标机器类型x64冲突,所以无论如何我无法链接这个旧库。

5 个答案:

答案 0 :(得分:3)

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

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

它也应该使用__cdecl,虽然我不确定。

答案 1 :(得分:3)

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

Calling 32bit Code from 64bit Process

答案 2 :(得分:3)

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

处理linke错误的一般方法:

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

    dumpbin / symbols

  2. 转储库和dll

    dumpbin / exports dumpbin / exports

  3. 对于静态库

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

    2. 您找到的任何不匹配都会表明您的问题是什么

    3. 将您的通话更改为与导出的内容相同的结果


    4. 解释(部分)结果:

      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位编译。