Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Fill Fortran Module Data in C

Stephen_W_
Novice
540 Views

I have a Fortran library with following structure:

module data
implicit none
real(8), allocatable :: x(:)
end module data

subroutine ff(y)
use data

do some stuff with x
end subroutine

the reason for introduce the module data is that x is large and there are more subroutines use x.

Usually, call this lib in Fortran is nothing but allocate x first then call ff. Now I want to call this lib from C, it is easy to use ISO_C_BINDING to call ff from C, but I don't know how to allocate and fill value for module data x in C, a working solution is that use a wrapper function, that reads C data and allocate x in Fortran, something like

subroutine cif(carray, n) bind(c)
use iso_c_binding, only: c_double, c_int
use data
implicit none
integer(c_int), intent(in) :: n
real(c_double), intent(in) :: carray(n)
X = carray
end subrountine

I think this wrapper function will allocate the global data x with size n and fill values stored in carray, but since x is large, here we essentially double store the same array, that is, in C, it is carray, and in Fortran is x, I wonder whether I can directly put the address of carray to x with a wrapper function, since I can not modify the Fortran lib.

0 Kudos
1 Solution
Arjen_Markus
Honored Contributor I
540 Views

No, it is simpler:

double *address;

alloc_n( 1000, &address );

address[0] = 1.0;
address[1] = 2.0;
...

No need to try and access the module variables - the routine simply gives you the address to work with on the C side.

View solution in original post

0 Kudos
8 Replies
andrew_4619
Honored Contributor II
540 Views

why not just create a bind(c) fortran routine that takes the size of X as a parameter and allocates X as this size?  You can then call this routine from C.

0 Kudos
Stephen_W_
Novice
540 Views

andrew_4619 wrote:

why not just create a bind(c) fortran routine that takes the size of X as a parameter and allocates X as this size?  You can then call this routine from C.

Then how can I initialize the X from C, without double store the large array? Thanks

0 Kudos
Arjen_Markus
Honored Contributor I
540 Views

Why not allocate the array on the Fortran side and pass its address to C for filling it? Something along these lines:

subroutine alloc_x(n , address ) bind(c)
     integer, value :: n
     type(c_ptr), intent(out) :: address

     allocate( x(n) )
    
     address = c_loc(x)
end subroutine alloc_n

Note: untested and possibly incomplete, but you get the idea, I hope.

0 Kudos
Stephen_W_
Novice
540 Views

Arjen Markus wrote:

Why not allocate the array on the Fortran side and pass its address to C for filling it? Something along these lines:

subroutine alloc_x(n , address ) bind(c)
     integer, value :: n
     type(c_ptr), intent(out) :: address

     allocate( x(n) )
    
     address = c_loc(x)
end subroutine alloc_n

Note: untested and possibly incomplete, but you get the idea, I hope.

Thanks, now `address` should be accessible from C, I get this to work by declaring `address` in the module statement and use `extern double *address` in C, is it necessary?

0 Kudos
Arjen_Markus
Honored Contributor I
541 Views

No, it is simpler:

double *address;

alloc_n( 1000, &address );

address[0] = 1.0;
address[1] = 2.0;
...

No need to try and access the module variables - the routine simply gives you the address to work with on the C side.

0 Kudos
Stephen_W_
Novice
540 Views

Arjen Markus wrote:

No, it is simpler:

double *address;

alloc_n( 1000, &address );

address[0] = 1.0;
address[1] = 2.0;
...

No need to try and access the module variables - the routine simply gives you the address to work with on the C side.

Many Thanks, it is working, another question is when I deallocate the X array in fortran, why I still can access the pointer address in C with the value filled, I am not sure whether it is free in C.

0 Kudos
Arjen_Markus
Honored Contributor I
540 Views

As a rule you should deallocate/free memory via the same language as you allocated it with. Each language system has its own administration for allocated memory. That said, the next thing to remember is that the operating system is ultimately responsible for freeing the memory. That may not actually happen until the program finishes. It is all up to the discretion of the OS. Simply do not rely on the memory being available after deallocation.

There is no point in trying to divine whether the C pointer is useable. It may seem so in one situation but in another it would lead to immediate disaster. So do not assume anything about it.
 

0 Kudos
Stephen_W_
Novice
540 Views

Got it, Thanks

0 Kudos
Reply