- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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_nNote: 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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Got it, Thanks
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page