Question

I currently have a C++ program which performs some tasks (not important here) and store some data into a 2D array which has been dynamically allocated (using C function malloc). It works well and I now need to have access to these data in a fortran program. I'm currently creating a program in Fortran which calls a subroutine in C/C++ performing the tasks I want, but when the 2D dynamically array is filled with data, I need to have access to it when back to the Fortran main program. The problem is I can't manage to get my data back to the Fortran main program (in an 2D allocatable array) I tried to code a simple program for passing a dynamic array allocated in a C subroutine, which is called by my main Fortran program, in order to see if I can get access to the data when I'm out of the C subroutine.

Here is my small code :

Fortran main:

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 subroutine:

#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);
}

This is really simple, but I get this output:

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 don't understand why I get this when i>1 I hope I was clear on my problem, can someone help please ?

Thanks a lot !

Was it helpful?

Solution

Your problem is that *x[i]=i; means *(x[i])=i;, but what you want is (*x)[i]=i;.

This happens because both x[i] and *x are pointers to int, so the compiler can't catch the error.
(*x[i] is equivalent to x[i][0], while (*x)[i] is equivalent to x[0][i].)

To avoid the issue, and the parentheses, you can rewrite like this:

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 added a test for i < s in order to avoid writing outside the array.

OTHER TIPS

Amongst other things, your interface in Fortran for the C++ function declares the pX argument to be allocatable. Note support for this requires a compiler that supports that feature from the future F201X standard. There aren't many of those.

I very much suspect this isn't what you intend - but if you did the C++ argument declaration is quite different from what you have. Consult the TS for further interoperability with C for more information.

You don't need or want pX to be allocatable, either as the variable in the main program or the argument. You are not "allocating" pX - it is a C_PTR that you want to define with the C address of some memory allocated by your C++ function.

Also, the s argument in the interface is declared without the VALUE attribute. That means that it corresponds to a pointer argument on the C side. Your C definition shows it being passed by value.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top