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)
Related
I have a Fortran function which compiled with previous versions of Intel Fortran Compiler (ifort), but is rejected by more recent versions (2021.6.0), and I hope to fix it. This function accepts a class(*), and passes its address and length to a C function:
!> Send an arbitrary scalar object.
function SendObject(my,obj) result(ok)
use, intrinsic :: iso_c_binding
implicit none
class(Socket) :: my
class(*), target, intent(in) :: obj
type(c_ptr) :: ptr
integer(c_size_t) :: len
ptr = c_loc(obj)
len = c_sizeof(obj)
ok = my%SendData(ptr,len)
end function
ifort now emits an error:
error #9023: The argument to C_LOC must not be polymorphic. [OBJ]
ptr = c_loc(obj)
While this function is polymorphic, in practice it is used only for a few simple structs containing scalars.
What is the best way to get this function "working" again, as well as it worked with previous compilers? I just need to get a C pointer to obj. Thanks for any help!
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 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.
In C++, I allocate an array of S. In Fortran, I want to access elements of this array. How can I do this?
C++:
struct S {double a; double b;};
S *arrayOfS;
arrayOfS = (S *)new S[123]; // allocate
Fortran 2003:
USE ISO_C_Binding
TYPE, BIND(C) :: SFortran
REAL(c_double) :: a,b
END TYPE SFortran
S and SFortran should now be interoperable, but I also need to have a way to access the elements of the array declared in C++. I'd like to have SC(5)%a in Fortran correspond to arrayOfS[4].a in C++. How do I declare and set the proper value for Fortran array SC that will have this access?
You could:
1) pass the C++ array to a Fortran BIND(C) procedure that takes an appropriate array argument.
SUBROUTINE proc(array) BIND(C, NAME='proc')
...
TYPE(SFortran) :: array(*)
WIth this approach you might also want to pass the size of the array across and make the array argument explicit shape.
b) have the array pointer as an extern "C" global on the C++ side, and then interoperate through a Fortran module variable with BIND(C).
MODULE some_module
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR, C_F_POINTER
...
TYPE(C_PTR), BIND(C, NAME='arrayOfS') :: array_ptr
...
! In a procedure in the module...
TYPE(SFortran), POINTER :: array(:)
CALL C_F_POINTER(array_ptr, array, [123])
Again it might suit to have size of the array available separately to avoid hard coding it in the C_F_POINTER reference.
Which approach is best depends on your requirements!