I have a code in C++ and I would like to call some functions in Fortran. I have the following function
Vector3d CWLiDAR__get_position(CWLiDAR* This)
{
return This->get_position();
}
There is a wrapper in Fortran:
module CWLiDAR_module
use, intrinsic :: ISO_C_Binding
implicit none
private
type CWLiDAR_type
private
type(C_ptr) :: object = C_NULL_ptr
end type CWLiDAR_type
interface
function C_CWLiDAR__get_position (this) result(pos) bind(C, name="CWLiDAR__get_position")
import
type(C_ptr), value :: this
real(C_double), intent(out), dimension(*) :: pos
end function C_CWLiDAR__get_position
end interface
interface get_position
module procedure CWLiDAR__get_position
end interface get_position
public :: get_position, CWLiDAR_type
contains
function CWLiDAR__get_position(this) result(pos)
type(CWLiDAR_type), intent(in) :: this
double precision, dimension(0:3) :: pos
pos = C_CWLiDAR__get_position(this%object)
end function CWLiDAR__get_position
end module CWLiDAR_module
However I am getting the following compilation error:
function C_CWLiDAR__get_position (this) result(pos) bind(C, name="CWL
1
Error: Assumed size array at (1) must be a dummy argument
function C_CWLiDAR__get_position (this) result(pos) bind(C, name="CWL
1
Error: Assumed size array at (1) must be a dummy argument
How can I pass a Vector3D to Fortran?
Functions which return arrays are NOT interoperable with C. You cannot call such a function from Fortran. At least not portably using bind(C).
If it was possible (but it isn't!) the syntax would have to be
interface
function C_CWLiDAR__get_position (this) result(pos) bind(C, name="CWLiDAR__get_position")
import
type(C_ptr), value :: this
real(C_double), dimension(some_number) :: pos
end function C_CWLiDAR__get_position
end interface
The compiler is complaining that neither intent, nor dimension(*) is allowed for function results in Fortran. That is the reason for the error message.
Related
I have a Fortran DLL which is called from a C program, and one of my procedures needs periodically to call a callback function which is supplied by the C program. I currently have it working well in its 'simple' form, but I'd like to be able to store my callback pointer inside a derived type, so that it can be passed around within my Fortran code more easily. So far, nothing I've tried seems to work.
To begin with, here is what I have at the moment, and this does work:
Starting in the C (OK, actually C++) program, the header prototype for the callback is:
typedef void (*fcb)(void *)
and the prototype for the Fortran call is:
extern "C" __declspec(dllexport) int fortran_function(int n,
uchar *image_buffer,
fcb callback,
void *object);
The actual callback function is:
void callback(void* pObject)
{
// Cast the void pointer back to the appropriate class type:
MyClass *pMyObject = static_cast<MyClass *>(pObject);
pMyObject -> updateImageInGUI();
}
and the call to the Fortran code from C++ is:
int error = fortran_function(m_image.size(), m_image.data, callback, this);
where m_image is an array of image data which is a member attribute of the current object. What happens is that the C++ passes the raw image data to the Fortran DLL and asks the Fortran to process it, and since this takes a long time the Fortran periodically updates the image buffer and calls the callback to refresh the GUI. Anyway, moving on to the Fortran side, we define an interface for the C callback:
abstract interface
subroutine c_callback(c_object) bind(c)
use, intrinsic :: iso_c_binding
type(c_ptr), intent(in) :: c_object
end subroutine c_callback
end interface
and define our main Fortran routine thus:
integer(c_int) fortran_function(n, image, callback, c_object) &
bind(c, name='fortran_function')
integer(c_int), value :: n
integer(4), intent(inout), dimension(n) :: image
procedure(c_callback) :: callback
type(c_ptr), intent(in) :: c_object
Somewhere in the main routine we call our subroutine, foo:
call foo(data, callback, c_object)
...where foo is defined as:
subroutine foo(data, callback, c_object)
type(my_type), intent(inout) :: data
procedure(c_callback) :: callback
type(c_ptr), intent(in) :: c_object
...
call callback(c_object)
...
end function foo
As I said, all of this works well and has done so for a long time.
Now for the things I've tried but which don't work:
The naive approach, just copying the arguments into the fields of a structure
I'd expect this to work, since all all I'm doing is to copy the original elements into a structure with no modification. Nothing changes on the C side, nor in the definition of the main Fortran function nor the abstract interface to c_callback. All I do is to create a new Fortran derived type:
type :: callback_data
procedure(c_callback), pointer, nopass :: callback => null()
type(c_ptr) :: c_object
end type callback_data
and then in my main function I populate this with the values received from the C application:
data%callback_data%callback => callback
data%callback_data%c_object = c_object
call foo(data)
The subroutine foo has been slightly modified so that it now looks for the callback and C object within the structure:
subroutine foo(data)
type(my_augmented_type), intent(inout) :: data
...
call data%callback_data%callback(data%callback_data%c_object)
...
end function foo
This fails at the call with an "access violation reading location 0xffffffffffffffff".
The sophisticated approach using more of the iso_c_binding features
Again nothing changes on the C side but I modify the Fortran side of the main function to receive the callback as a c_funptr:
integer(c_int) fortran_function(n, image, callback, c_object) &
bind(c, name='fortran_function')
integer(c_int), value :: n
integer(4), intent(inout), dimension(n) :: image
type(c_funptr), intent(in) :: callback
type(c_ptr), intent(in) :: c_object
I define the abstract interface to subroutine c_callback just as before, though I've experimented both with leaving the bind(c) part of it in, and omitting it. The code within the main function that calls the subroutine foo is now:
call c_f_procpointer(callback, data%callback_data%callback)
data%callback_data%c_object = c_object
call foo(data)
...with the subroutine foo itself still defined as in the previous example.
Unfortunately this fails in exactly the same way as the previous example.
I assume that there is a correct syntax to achieve what I'm trying to achieve here, and I'd be very grateful for any advice.
A dummy argument in a Fortran procedure with the BIND(C) attribute that doesn't have the VALUE argument is equivalent on the C side to a pointer parameter (this is broadly consistent with the usual Fortran convention of things being passed by reference). So if on the Fortran side you have INTEGER(C_INT) :: a (no value attribute), that's equivalent on the C side to int *a.
Perhaps that's obvious, but it has a surprising consequence - if you have TYPE(C_PTR) :: p, that's equivalent to void **p - a C_PTR is a pointer, so a C_PTR passed without value is a pointer to a pointer. Given this, your interface for the callback is out (you need to add VALUE).
The interoperable analogue in a type sense to a C pointer to a function (which is what a function name sans parentheses is in C) in Fortran is a TYPE(C_FUNPTR). The same considerations with respect to the absence of the VALUE attribute and C_PTR apply - an argument declared TYPE(C_FUNPTR) :: f is a pointer to a pointer to a function. Given this and your C side call of the Fortran, the argument corresponding to the function pointer should have the VALUE attribute.
The fact that a Fortran procedure pointer happens to work is just a (not terribly surprising) coincidence of the underlying implementation of C function pointers and Fortran procedure pointers, and the way that Fortran procedure pointers are passed.
All up, your Fortran procedure probably needs to have an interface that looks like:
integer(c_int) fortran_function(n, image, callback, c_object) &
bind(c, name='fortran_function')
integer(c_int), value :: n
integer(c_signed_char), intent(inout), dimension(n) :: image
type(c_funptr), intent(in), value :: callback
type(c_ptr), intent(in), value :: c_object
(your declaration of the image array in your original code seems astray - perhaps the above is appropriate, perhaps not)
and your declaration of the interface of the C callback needs to have an interface of:
abstract interface
subroutine c_callback(c_object) bind(c)
use, intrinsic :: iso_c_binding
implicit none
type(c_ptr), intent(in), value :: c_object
end subroutine c_callback
end interface
(As discussed on the Intel fora over the last few months (where have you been?), current ifort may have a problem with it's handling of C_PTR and VALUE.)
I am converting some of our Fortran library code into C so that we finally have C functions with Fortran wrappers around it. We are using Fortran 95.
What is the preferred way to handle allocatable arrays?
Can I pass an allocatable array to a C function and malloc it inside the C function?
(The C function knows the size to be malloc'ed)
In the fortran program, can I deallocate something that was malloced in a C function?
So finally either the client fortran application deallocates the array or is required to call a C function that frees the memory.
A small example or a link to one would be highly appreciated.
In Fortran 95 you can't "pass" allocatable arrays as an allocatable thing to anything, including Fortran procedures.
In Fortran 2003, the C function can malloc storage for the array, and then return that to the Fortran side as a C_PTR from the ISO_C_BINDING intrinsic module. The storage pointed to by the C_PTR can then be accessed using a Fortran POINTER and the C_F_POINTER procedure from the ISO_C_BINDING module.
To free the storage for the array, the Fortran side would again call into a C procedure, passing the C_PTR, which the C function then uses in a call to free.
#include "stdlib.h"
int *create_storage()
{
/* Array of four integers. */
return malloc(sizeof(int) * 4);
}
void destroy_storage(int *ptr)
{
free(ptr);
}
PROGRAM fortran_side
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR, C_F_POINTER, C_INT
IMPLICIT NONE
INTERFACE
FUNCTION create_storage() BIND(C, NAME='create_storage')
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR
IMPLICIT NONE
TYPE(C_PTR) :: create_storage
END FUNCTION create_storage
SUBROUTINE destroy_storage(p) BIND(C, NAME='destroy_storage')
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR
IMPLICIT NONE
TYPE(C_PTR), INTENT(IN), VALUE :: p
END SUBROUTINE destroy_storage
END INTERFACE
TYPE(C_PTR) :: p
INTEGER(C_INT), POINTER :: array(:)
!****
p = create_storage()
CALL C_F_POINTER(p, array, [4]) ! 4 is the array size.
! Work with array...
CALL destroy_storage(p)
END PROGRAM fortran_side
In Fortran 201X, C header files and functions may be provided to allow C to work directly with Fortran allocatable variables.
I would like to know how to create a function that either returns a real, an integer or a string.
For example, the call would be write(*,*)dt%get() where get() would return :
an integer if dt%isInteger = .true.
a real if dt%isReal = .true.
a character if dt%isStr = .true.
I believe this might be possible by using an abstract interface to make procedure get() point to either procedure getInteger(), getReal() or getStr() but the abstract interface definition needs to define the ouput type which is, in my case, variable.
Here is the related code:
type :: dt
real(dp) :: realValue
integer :: integerValue
character(*) :: strValue
logical :: isReal, isInteger, isStr
procedure(intf), pointer :: get
contains
procedure :: getReal, getInteger, getStr
end type
abstract interface
function intf(self)
import dt
class(dt) :: self
??? :: intf
end function
end interface
Any idea ?
That is simply impossible in Fortran.
You can use a generic interface with different specific functions, but these functions must have arguments of different types (see how several intrinsic functions, like transfer() use a mold argument). This is called the TKR (type, kind, rank) resolution. Generic functions cannot be distinguished based on a value of an argument.
type :: dt
real(dp) :: realValue
integer :: integerValue
character(*) :: strValue !!!! <= THIS IS WRONG !!!!
logical :: isReal, isInteger, isStr
contains
generic :: get => getReal, getInteger, getStr
procedure :: getReal, getInteger, getStr
end type
function getReal(self, mold)
class(dt) :: self
real, intent(in) :: mold
end function
function getInteger(self, mold)
class(dt) :: self
integer, intent(in) :: mold
end function
function getString(self, mold)
class(dt) :: self
character(*), intent(in) :: mold
end function
As you see, you have to know the correct type when calling get(). You call it like
real_variable = object%get(1.0)
integer_variable = object%get(1)
Be also careful about strings of different lengths. I marked it above. You probably want character(:), allocatable.
You can make also function which returns a generic container and then extract the value from the container. The extraction could even be done directly using an overloaded assignment for the container.
You could also just return an unlimited polymorphic variable (class(*)).
I am trying to pass a procedure pointer to a derived-type-bound-procedure
module mymodule
use mystoremodule
implicit none
private
type, abstract, public :: mytype
contains
procedure :: parse
end type mytype
contains
subroutine parse(self,mypointer)
implicit none
! Declaring Part
class(mytype) :: self
procedure(storing),pointer, intent(in) :: mypointer
integer :: myvalue
! Executing Part
myvalue = 42
call mypointer(myvalue)
end subroutine parse
end module mymodule
where storing is defined in another module/ derived type
module mystoremodule
implicit none
type, public :: storingtype
integer :: myvalue
contains
procedure, public :: storing
end type storingtype
contains
subroutine storing(self,myvalue)
! Declaring part
class(storingtype) :: self
integer, intent(in) :: myvalue
! Executing part
self%myvalue = myvalue
end subroutine SetExcitationOrder
end module mystoremodule
I call the procedure by
call mytypeobject%parse(storingtypeobject%storing)
With that i get a compiler error
The type of the actual argument differs from the type of the dummy argument.
I found out that the error comes from the procedure pointer not passing the dummy argument to the storing procedure (i didn't define anything as nopass). In all other cases the dummy argument gets passed automatically, why not here? It's not feasible for me to declare the dummy argument, as the object which the procedure uses changes.
Are there any solutions to my problem?
Well you are not passing there a procedure pointer. storingtypeobject%storing is not a procedure pointer, it is a binding to a type-bound procedure, not a pointer of any kind.
I wouldn't actually accept a pointer, but just a procedure argument in parse.
Something like:
subroutine parse(self,mypointer)
implicit none
! Declaring Part
class(mytype) :: self
procedure(storing), intent(in) :: myproc
integer :: myvalue
! Executing Part
myvalue = 42
call myproc(myvalue)
end subroutine parse
and
call mytypeobject%parse(storing_wrapper)
contains
subroutine storring_wrapper(myvalue)
integer, intent(in) :: myvalue
call storingtypeobject%storing(myvalue)
end subroutine
I think procedure pointers are mostly useful only if it can be changed somewhere. Not necessarily in parse but if you need to set it to some other target in some situations.
I have a problem with connecting Fortran program with C++ function.
My task is to call C++ function pointer from fortran, example:
// C++ function pointer
double* GetSplinePtr()
{
return sp;
}
I use iso_c_binding procedure and fortran interface.
For non-pointer function i usually use this declaration:
real(kind=c_double) function Name(x,y) bind(c, name='Name')
use iso_c_binding
implicit none
real(c_double), intent(in), value :: x,y
end function Name
But what should I use for function which returns a pointer?
Thanks!
As Ross comments, you must make the Fortran interface to return the C pointer and do the conversion to a Fortran pointer yourself.
interface
function GetSplinePtr() result(res) bind(C, name="GetSplinePtr")
use iso_c_binding
type(C_ptr) :: res
end function
end interface
In the calling code you have to call c_f_pointer() from the iso_c_binding module:
use iso_c_binding
type(c_ptr) :: p
real(c_double), pointer :: x
p = GetSplinePtr()
call c_f_pointer(p, x)