Reputation: 145
I have the following C++ code:
extern "C" void C_ASSIGN_ARRAY_TO_FORTRAN(double *doublearray)
{
doublearray=new double [10];
for (int i=0;i<10;i++)
doublearray[i]=i;
}
The array doublearray
should be passed to 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
However, the code crashed at C_F_POINTER
: after calling C_ASSIGN_ARRAY_TO_FORTRAN
, cdoublearray
is equal to 0
.
Could anyone help me to take a look at it?
Upvotes: 2
Views: 1728
Reputation: 18118
You are passing the pointer by value, and not by reference. Your C++ code should read
extern "C" void C_ASSIGN_ARRAY_TO_FORTRAN(double *& doublearray)
{
doublearray=new double [10];
for (int i=0;i<10;i++)
doublearray[i]=i;
}
Note the C_ASSIGN_ARRAY_TO_FORTRAN(double *& doublearray)
.
An alternative way using C Pointers (thanks Vladimir) could look like:
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;
}
Using the fix that Vladimir suggested, the Fortran code reads
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
Then, the output is
./a.out
fdoublearray 0.0000000000000000 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 5.0000000000000000 6.0000000000000000 7.0000000000000000 8.0000000000000000 9.0000000000000000
Upvotes: 1
Reputation: 60088
You are passing a copy of the pointer here
CALL C_ASSIGN_ARRAY_TO_FORTRAN((cdoublearray))
the copy is made by the second set of parentheses. Therefore the cdoublearray
is never changed and keeps the original undefined value which happens to e 0.
Try
CALL C_ASSIGN_ARRAY_TO_FORTRAN(cdoublearray)
but be careful, you will still have a problem when deallocating the array. That must be done from C++.
You must also adjust the procedure to accept a pointer to pointer. See @AlexenderVogt's answer.
Upvotes: 2