从Fortran调用的c++子程序:如何处理动态内存分配

Subroutine C++ called from Fortran : How to deal with Dynamic memory allocation?

本文关键字:处理 动态 分配 内存 何处理 调用 Fortran c++ 子程序      更新时间:2023-10-16

我目前有一个c++程序,它执行一些任务(这里不重要),并将一些数据存储到一个动态分配的2D数组中(使用C函数malloc)。它工作得很好,我现在需要在fortran程序中访问这些数据。我目前正在创建一个程序在Fortran调用子程序在C/c++执行我想要的任务,但当二维动态数组充满数据,我需要有访问它时,回到Fortran主程序。问题是我无法让我的数据回到Fortran主程序(在2D可分配数组)我试图编写一个简单的程序,用于传递在C子例程中分配的动态数组,这是由我的主要Fortran程序调用的,以查看当我离开C子例程时是否可以访问数据。

下面是我的小代码:

Fortran主要:

PROGRAM FORT_C
use iso_c_binding
IMPLICIT NONE
interface
    subroutine call_fc(pX,s) bind(C,name='call_fc_')
        import
        integer(c_int)              :: s
        type(c_ptr), allocatable    :: pX
    end subroutine
end interface
integer(c_int)                              :: i
integer(c_int), pointer                     :: X(:)
type(C_ptr), allocatable                    :: pX

call call_fc(pX,100)
call c_f_pointer(pX,X,[100])
END

C子例程:

#include <cstdlib>
#include <iostream>
using namespace std;
extern "C" 
{
    void call_fc_(int **x, int s);
    void c_func_deallocate(int **x);
}

void call_fc_(int **x, int s)
{
    int i;
    *x = (int *) malloc(sizeof(int)*s);
    for(i=0;i<100;i++)
    {
        cout << i << endl;
        *x[i]=i;
    }
}
void c_func_deallocate(int **x)
{
    free(*x);
}

这真的很简单,但是我得到了这个输出:

0
1
forrtl: severe (174): SIGSEGV, segmentation fault occurred
Image              PC                Routine            Line        Source             
exemple            000000000040304C  Unknown               Unknown  Unknown
exemple            0000000000402F25  Unknown               Unknown  Unknown
exemple            0000000000402ECC  Unknown               Unknown  Unknown
libc.so.6          000000331241ECDD  Unknown               Unknown  Unknown
exemple            0000000000402DC9  Unknown               Unknown  Unknown

我不明白为什么我得到这个当I>1我希望我把我的问题讲清楚了,有人能帮帮我吗?

你的问题是,*x[i]=i;意味着*(x[i])=i;,但你想要的是(*x)[i]=i;

发生这种情况是因为x[i]*x都是指向int的指针,所以编译器无法捕获错误。
(*x[i]相当于x[i][0], (*x)[i]相当于x[0][i])

为了避免这个问题和括号,您可以这样重写:

void call_fc_(int **x, int s)
{
    int i;
    int *y = (int *) malloc(sizeof(int)*s);
    for(i = 0; i < 100 && i < s; i++)
    {
        cout << i << endl;
        y[i]=i;
    }
    *x = y;
}

我为i < s添加了一个测试,以避免在数组外写入。

在Fortran中,c++函数的接口声明pX参数是可分配的。注意,支持此功能需要编译器支持未来F201X标准中的该功能。这样的人不多。

我非常怀疑这不是你想要的——但是如果你这样做了,c++的参数声明与你所拥有的完全不同。有关更多信息,请参阅TS以了解与C的进一步互操作性。

不需要也不希望pX是可分配的,无论是作为主程序中的变量还是参数。你不是在"分配"pX——它是一个C_PTR,你想用c++函数分配的一些内存的C地址来定义它。

同样,接口中的s参数声明不带VALUE属性。这意味着它对应于C端的一个指针参数。您的C定义显示它是按值传递的。