Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
2 Views

Fill Fortran Module Data in C

Jump to solution

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.

Econometrics
0 Kudos

Accepted Solutions
Highlighted
Valued Contributor II
2 Views

No, it is simpler:

Jump to solution

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
Highlighted
Valued Contributor II
2 Views

why not just create a bind(c)

Jump to solution

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
Highlighted
Beginner
2 Views

Quote:andrew_4619 wrote:

Jump to solution

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

Econometrics
0 Kudos
Highlighted
Valued Contributor II
2 Views

Why not allocate the array on

Jump to solution

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
Highlighted
Beginner
2 Views

Quote:Arjen Markus wrote:

Jump to solution

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?

Econometrics
0 Kudos
Highlighted
Valued Contributor II
3 Views

No, it is simpler:

Jump to solution

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
Highlighted
Beginner
2 Views

Quote:Arjen Markus wrote:

Jump to solution

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.

Econometrics
0 Kudos
Highlighted
Valued Contributor II
2 Views

As a rule you should

Jump to solution

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
Highlighted
Beginner
2 Views

Got it, Thanks

Jump to solution

Got it, Thanks

Econometrics
0 Kudos