【问题标题】:Calling C++ function from Fortran in Visual Studio 2010 with 2003 ISO C binding在具有 2003 ISO C 绑定的 Visual Studio 2010 中从 Fortran 调用 C++ 函数
【发布时间】:2013-02-27 16:33:43
【问题描述】:

我必须从我的 fortran 程序中调用一个 C++ 函数。我正在使用 Visual Studio 2010。我阅读了本书 http://www.amazon.com/Guide-Fortran-Programming-Walter-Brainerd/dp/1848825420 中有关 2003 ISO C 绑定的相关章节。我试图编译并运行第 219 页的简单示例(我在下面复制了它),但它显示“错误 LNK2019:未解析的外部符号 _c 在函数 _MAIN__ 中引用”。这些是我遵循的步骤。

1)我用Fortran主程序和模块创建了一个Fortran项目,并将其设置为“启动项目”。

2)我创建了一个“静态库”类型的 C++ 项目。

3)我添加了 $(IFORT_COMPILERvv)\compiler\lib\ia32 ,正如此处http://software.intel.com/en-us/articles/configuring-visual-studio-for-mixed-language-applications 所解释的那样

当我编译时,我得到了那个错误。如果我评论 Call C 行,它会完美运行,所以它找不到 C 函数。有什么建议吗?提前致谢。以下是 C 和 Fortran 代码:

    module type_def
       use, intrinsic :: iso_c_binding
       implicit none
       private

       type, public, bind(c) :: t_type
          integer(kind=c_int) :: count
          real(kind=c_float) :: data
       end type t_type
    end module type_def

    program fortran_calls_c
       use type_def
       use, intrinsic :: iso_c_binding
       implicit none

       type(t_type) :: t
       real(kind=c_float) :: x, y
       integer(kind=c_int), dimension(0:1, 0:2) :: a

       interface
          subroutine c(tp, arr, a, b, m) bind(c)
             import :: c_float, c_int, c_char, t_type
             type(t_type) :: tp
             integer(kind=c_int), dimension(0:1, 0:2) :: arr
             real(kind=c_float) :: a, b
             character(kind=c_char), dimension(*) :: m
          end subroutine c
       end interface

       t = t_type(count=99, data=9.9)
       x = 1.1
       a = reshape([1, 2, 3, 4, 5, 6], shape(a))
       call c(t, a, x, y, "doubling x" // c_null_char)
       print *, x, y
       print *, t
       print *, a

    end program fortran_calls_c

    #include "stdafx.h"
    //#include <iostream>
    #include <fstream>
    typedef struct {int amount; float value;} newtype;
    void c(newtype *nt, int arr[3][2], float *a, float *b, char msg[])
    {
        printf (" %d %f\n", nt->amount, nt->value);
        printf (" %d %d %d\n", arr[0][1], arr[1][0], arr[1][1]);
        printf (" %s\n", msg);
        *b = 2*(*a);
    }

【问题讨论】:

  • 您的 c++ 函数名称将被破坏。要停止此操作,请使用 extern "c"
  • 谢谢,但我尝试用 extern "C" void c(....) 替换 C++ 代码中的行,但没有任何改变...
  • 好吧,没有一个真正知道他们在做什么的人在这里插话......我前段时间玩过这个,从来没有在 Windows 上玩过,但是哦,好吧。现在我有一个模糊的记忆,编译器会在 Fortran 中的函数名末尾添加一个 _。但是在这种情况下,错误是unresolved external symbol _c,所以它看起来像在 Windows 中它在前面。试试extern "c" void _c (newtype *nt, int arr[3][2], float *a, float *b, char msg[]){...}
  • 啊,我根本没有 Windows。我想建议切换到真正的操作系统,但不知何故我怀疑这不是一个有用的答案。阅读this。你是编译c++ 64位的吗?
  • 伙计们,如果我充分理解了 2003 C 绑定已经解决了所有重命名问题。否则我们为什么要使用它?事实上,下面的答案是可行的,但你必须这样做并且为你添加的每个 C++ 项目这样做是很奇怪的。

标签: c++ visual-studio fortran fortran-iso-c-binding


【解决方案1】:

现已编辑答案以反映 IanH 评论中的建议和知识:

正如@BoBTFish 建议的那样,将extern "C" 插入C++ 函数c 的声明中。当然,请确保您使用大写字母 C,那里的一些评论有点松散。

我注释掉了包含stdafx.h 的源代码行,这似乎是可选的,我懒得寻找或创建它。

在那之后,对于 Fortran 项目,

  • 链接器/常规/附加库目录到lib文件所在的目录;和
  • 链接器/输入/附加依赖项指定lib文件。

将 C++ 和 Fortran 项目的运行时库选项设置为相同。在 Fortran 项目的属性页面中,将 Fortran / Libraries 设置为 Debug Multithread DLL

现在它编译并执行并生成以下内容:

 99 9.900000
 2 3 4
 doubling x
   1.100000       2.200000
          99   9.900000
           1           2           3           4           5           6

感谢 IanH 的投入,我现在是一个更明智的脚本跟随猴子。

【讨论】:

  • 谢谢它的工作。但是有人可以详细说明一下吗?忽略 MSVCRTD.lib 是否安全。为什么这个错误与 MSVCRTD.lib 有关?我仍然有一些磨损: 1>ipo: 警告 #11073: provaC.lib(prova.obj): 本地定义的符号 __imp__printf 导入 1>provaC.lib(prova.obj) : 警告 LNK4075: 忽略'/EDITANDCONTINUE'由于 '/INCREMENTAL:NO' 规范 1>provaC.lib(prova.obj):警告 LNK4217:在函数 _c 中导入的本地定义符号 _printf
  • 还有警告:1>警告LNK4204:'..\vc100.pdb'缺少引用模块的调试信息;链接对象好像没有调试信息
  • 有关 MSVCRTD.lib 的警告可能是因为您有两个不同的 C 运行时库实例(一个基于 DLL,一个静态)链接到同一个可执行文件。而不是“忽略特定库”,而是将 C++ 和 Fortran 项目的运行时库选项设置为相同 - 可能将 Fortran > 库 > 运行时库下的 Fortran 设置更改为 [调试] 多线程 DLL。
  • 是的,谢谢我现在选择了静态多线程,它不会产生任何错误或警告(我显然不再忽略 MSVCRTD.lib)。
  • 我快疯了......这适用于这个例子......然后当我尝试将我的个人 fortran 项目与另一个 C++ 项目链接时,即使使用调试多线程 (/libs:静态/线程/dbglibs)。我解决了 C++property -> configurations ->general -> use of MFC ->Use MFC in a Static Library 中的更改。这很奇怪,因为上面的示例仅适用于“使用标准 Windows 库”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-23
  • 1970-01-01
  • 2011-08-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多