【问题标题】:How to pass C++ pointer to Fortran?如何将 C++ 指针传递给 Fortran?
【发布时间】:2015-05-10 13:36:34
【问题描述】:

我有以下 C++ 代码:

extern "C" void C_ASSIGN_ARRAY_TO_FORTRAN(double *doublearray)
{
    doublearray=new double [10];
    for (int i=0;i<10;i++)
        doublearray[i]=i;
}

数组doublearray 应该传递给Fortran:

  USE, INTRINSIC :: ISO_C_BINDING
  IMPLICIT NONE
  INTERFACE
    SUBROUTINE C_ASSIGN_ARRAY_TO_FORTRAN(cdoublearray) BIND(C, NAME='C_ASSIGN_ARRAY_TO_FORTRAN')
    USE, INTRINSIC :: ISO_C_BINDING
      IMPLICIT NONE
      TYPE(C_PTR)  :: cdoublearray
    END SUBROUTINE 
  END INTERFACE

  TYPE(C_PTR) :: cdoublearray
  REAL(C_DOUBLE), POINTER :: fdoublearray(:)
  CALL C_ASSIGN_ARRAY_TO_FORTRAN((cdoublearray))
  CALL C_F_POINTER( cdoublearray, fdoublearray,[10])  
  WRITE (*, *) fdoublearray
  END   

但是,代码在C_F_POINTER 崩溃:调用C_ASSIGN_ARRAY_TO_FORTRAN 后,cdoublearray 等于0。 谁能帮我看看?

【问题讨论】:

  • 您的问题到底是什么?它编译吗?是不是跑错了?
  • 调用C_ASSIGN_ARRAY_TO_FORTRAN后,cdoublearray等于0,所以运行到C_F_POINTER时程序就破解了。
  • 为什么你将cdoublearray作为副本传递((cdoublearray))
  • 破解了什么?它打印了什么吗?
  • 你的意思是“崩溃”吗?

标签: c++ pointers fortran fortran-iso-c-binding


【解决方案1】:

你在这里传递了一个指针的副本

CALL C_ASSIGN_ARRAY_TO_FORTRAN((cdoublearray))

副本由第二组括号组成。因此cdoublearray 永远不会改变并保持原来的未定义值,这恰好发生在 e 0 上。

试试

CALL C_ASSIGN_ARRAY_TO_FORTRAN(cdoublearray)

但要小心,在解除分配数组时仍然会遇到问题。这必须从 C++ 中完成。

您还必须调整过程以接受指向指针的指针。请参阅@AlexenderVogt 的回答。

【讨论】:

  • 感谢您的建议。我已将代码更改为通过 C++ 释放内存。
【解决方案2】:

您是按值传递指针,而不是按引用传递。你的 C++ 代码应该是

extern "C" void C_ASSIGN_ARRAY_TO_FORTRAN(double *& doublearray)
{
    doublearray=new double [10];
    for (int i=0;i<10;i++)
        doublearray[i]=i;
}

注意C_ASSIGN_ARRAY_TO_FORTRAN(double *&amp; doublearray)

使用 C 指针的另一种方法(感谢 Vladimir)可能如下所示:

extern "C" void C_ASSIGN_ARRAY_TO_FORTRAN(double ** doublearray)
{
    double *arr = new double [10];
    for (int i=0;i<10;i++) 
        arr[i]= i;
    *doublearray = arr;
}

使用 Vladimir 建议的修复,Fortran 代码读取

program test
  USE, INTRINSIC :: ISO_C_BINDING
  IMPLICIT NONE
  INTERFACE
    SUBROUTINE C_ASSIGN_ARRAY_TO_FORTRAN(cdoublearray) BIND(C, NAME='C_ASSIGN_ARRAY_TO_FORTRAN')
    USE, INTRINSIC :: ISO_C_BINDING
      IMPLICIT NONE
      TYPE(C_PTR)  :: cdoublearray
    END SUBROUTINE 
  END INTERFACE

  TYPE(C_PTR) :: cdoublearray
  REAL(C_DOUBLE), POINTER :: fdoublearray(:)

  CALL C_ASSIGN_ARRAY_TO_FORTRAN( cdoublearray )
  CALL C_F_POINTER( cdoublearray, fdoublearray,[10])

  WRITE (*, *) 'fdoublearray',fdoublearray
END program

那么,输出是

./a.out 
 fdoublearray   0.0000000000000000        1.0000000000000000        2.0000000000000000        3.0000000000000000        4.0000000000000000        5.0000000000000000        6.0000000000000000        7.0000000000000000        8.0000000000000000        9.0000000000000000 

【讨论】:

  • &amp; 表示 C++ 引用,extern "C" 函数不支持它,Fortran 的 bind(C) 也不正式支持它,尽管它通常作为指针实现。应该使用 C 指针 *
  • 感谢您的热情回复。我按照您的建议进行了修改,但结果是一样的。
  • 只需在此处放置第二颗星,而不是与号。现在你有了一个指向 C++ 引用的指针。
  • 天啊!只是(cdoublearray) 导致错误!在我将CALL C_ASSIGN_ARRAY_TO_FORTRAN((cdoublearray)) 更改为CALL C_ASSIGN_ARRAY_TO_FORTRAN(cdoublearray) 后,一切正常!我的意思是在使用了参考 & 之后。如何解释这种差异?谢谢
  • @Alexander & VladimirF 非常感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-06
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 2018-08-11
  • 2012-02-05
相关资源
最近更新 更多