Reputation:
I have a C program that has a function named get_name
. This function returns a string (i.e. char *
) and changes the argument size
(passed to it) with the size of the string:
char *get_name(int &size)
{
*size = strlen(name); // name is a C global variable declared as a char *
return name;
}
I have created the following Fortran module to be able to call the C function get_name
:
MODULE X
USE, INTRINSIC :: iso_c_binding, ONLY: c_intptr_t
IMPLICIT NONE
INTERFACE
TYPE(c_ptr) FUNCTION get_name_(size) BIND(C, name = "get_name")
USE, INTRINSIC :: iso_c_binding, ONLY: c_int, c_ptr
INTEGER(c_int), INTENT(OUT) :: size
END FUNCTION
END INTERFACE
CONTAINS
FUNCTION get_name()
USE, INTRINSIC :: iso_c_binding, ONLY: c_int, c_char, c_f_pointer, c_ptr, c_associated
!DEC$ ATTRIBUTES DLLEXPORT :: get_name
CHARACTER(LEN = :), ALLOCATABLE :: get_name
INTEGER(c_int) :: size
TYPE(c_ptr) :: c_string
c_string = get_name_(size)
IF (c_associated(c_string)) THEN
BLOCK
CHARACTER(KIND = c_char, LEN = size), POINTER :: f_string
CALL c_f_pointer(c_string, f_string)
get_name = f_string
END BLOCK
ELSE
get_name = ""
END IF
END FUNCTION
END MODULE
I can successfully compile this Fortran module using IFORT 2016 in Windows, IFORT 2016 in Linux, and gfortran in Linux.
To test things, I have created a short Fortran program:
PROGRAM Test
USE X
WRITE(*, *) "Name: ", get_name()
END PROGRAM
I can successfully compile this Fortran program using IFORT 2016 in Windows, IFORT 2016 in Linux, and gfortran in Linux.
Now, when running the program it works well in IFORT 2016 for Linux, gfortran in Linux, but not in IFORT 2016 for Windows. It actually gives the following error:
forrtl: severe (157): Program Exception - access violation
Any idea how this error can be solved?
Upvotes: 0
Views: 1361
Reputation: 782
I assume your C function is char *get_name(int *size)
instead of using a C++ reference.
Then this code works here on Windows and Linux with Ifort 16 and gcc-6.3.1 or Visual Studio 2015.
Please add your used C compiler and command lines to compile the code. I used:
cl -c testc.c && ifort -c testf.f /extend-source:132 && ifort testm.f testf.obj testc.obj /extend-source:132 && testm.exe
Btw: If you are using this function in parallel code I would suggest to avoid the block construct - I had bad experience using this in parallel (OpenMP) code with Ifort 16.
Upvotes: 2