- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello
I have a c function which receives an array of doubles and make changes to it.
for example:
on the "c" side
void DoSomething (double **values);
on the "fortran" side I have
real*8 values(*)
pointer(pvalues,values)
call DoSomething(pvalues)
in order to make the connection I create a module with and interface
module f_calling_c
interface
subroutine DoSomething(pvalues) Bind(C,Name="DoSomething")
USE , INTRINSIC :: ISO_BINDING
REAL (KIND=C_DOUBLE), pointer :: pvalues
end subroutine DoSomething
end Interface
end module f_calling_c
when I compile the fortran code I get the following errors
error #6633 the type of the actual argument differs from the type of the dummy argument [pvalues]
error #7496 a non-pointer actual argument shall have a target attribute when associated with a pointer dummy argument [pvalues]
I know I am doing something wrong
any help would really be appreciated
best
jac
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The problem is that Fortran pointers are not equivalent to C pointers. As you have a double indirection - double **values - the type on the Fortran side should be a generic one, type(*). By NOT specifying the attribute "value" on the Fortran side, you make sure that on the C side it can be seen as a void ** argument and that is what you need.
Caveat: I have not tested this ;).
If the argument on the C side had been double *values, then the Fortran side might have been:
real(c_double), dimension(*) :: values
or:
real(c_double), intent(inout) :: values
(I have added the intent just to show you the ambiguity of C pointers)
Is the C function allocating the array of values? That would present different difficulties.
Before I continue speculating, could you explain what the C function actually does? There is ample ambiguity here and on the Fortran side you may need to be specific.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi
thanks for your reply
so I can't pass a pointer on the fortran side ?
yes on the C side, the function allocates memory for the passed pointer
best
jac
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can pass C pointers to and from Fortran, that is not the problem. The thing is that an argument of type "double *" in a C function could mean two things (maybe even more): it is the starting address of an array of double-precision numbers or it is the address of a scalar and the function will change its value. In your case the C function allocates an array and returns the address. If you need to deallocate the memory, then that should be done on the C side.
To use the array in Fortran, use code like:
call c_f_pointer( c_ptr, farray [size] )The interface of the C function may be:
interface
subroutine DoSomething( allocated_ptr ) bind(C,name="DoSomething")
use iso_c_binding, only: c_ptr
type(c_ptr), intent(out) :: allocated_ptr
end subroutine DoSomething
end interfaceSince Fortran passes arguments by reference (by default, that is), you have a double indirection as required in this way.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
hi
thanks a lot for your support . True that pointers in c/c++ can be ambiguous
I tried what you suggested
module fci
interface
subroutine do_something (pvol,n) bind(C,NAME="do_something")
use iso_c_binding, only: c_ptr , c_int
type(c_ptr), intent(out) :: pvol
integer(KIND=C_INT), intent(in) :: n
end subroutine do_something
end interface
end module fci
the fortran function is as follows
use fci
pointer (ipvol, vol)
real*8 vol(*)
call do_something(pvol,10)
the module compiles fine but the main code does not
I get the following error
error #6633: The type of the actual argument differs from the type of the dummy argument. [PVOL]
it seems that there is need to specify the type of the pointer but I do not know how
best
jac
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You are using a so-called Cray pointer - an extension that has been superseded by the pointers that were introduced in the Fortran 90 standard. What you should do instead is something along these lines:
use fci
use iso_c_binding
type(c_ptr) :: pvol
real(kind=kind(1.0d0)), pointer :: vol(:)
call do_something(pvol,10)
call c_f_pointer(pvol, vol, [10])Also: the declaration of n in the interface is probably best done as:
integer(kind=c_int), value :: nas the C function likely uses "int n" - which is a value, not a reference to an intent(in) variable.
Anyway, I took your code and the above fragment and created a working program ;).
And instead of REAL*8 I use the KIND= attribute, that is standard, whereas REAL*8 is a very common extension but an extension.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page