I am struggling with filling a string array in a C++ code. Here is what I tried to do:
main.f90:
program main
implicit none
character(len=100) arr(3)
call get_string_array(arr, 100, 3)
write(*,'(3(a,3x))') arr
end
cpp_func.cpp:
#include <cstring>
#include <algorithm>
using namespace std;
void ConvertToFortran(char* fstring, size_t fstring_len, const char* cstring)
{
size_t inlen = strlen(cstring);
size_t cpylen = min(inlen, fstring_len);
fill(fstring, fstring + fstring_len, ' ');
copy(cstring, cstring + cpylen, fstring);
}
extern "C"
{
void get_string_array_(char** arr, int len, int n)
{
const char* strings[] = {"duma1", "duma2", "duma3"};
for (int i = 0; i < n; i++)
ConvertToFortran(arr[i], len, strings[i]);
}
}
After compiling the two files as
ifx -c main.f90
icx -c cpp_func.cpp
ifx main.o cpp_func.o
I receive a segmentation fault. Could you please help me how to print array arr
properly within main.f90
?
*** Edit ***
Any solution which is able to pass a string array from C++ to Fortran would be appreciated.
First, you should use the C binding features of Fortran, to have a more robust code:
program main
use iso_c_binding
implicit none
character(len=100) arr(3)
interface get_string_array
subroutine get_string_array(a, len, n) bind(C)
import c_int, c_char
integer(c_int), value :: len, n
character(kind=c_char,len=1) :: a(*)
end subroutine
end interface
call get_string_array(arr, 100, 3)
write(*,'(a)') arr
end
As you can see the interface of the C routine is described. In particular, len
and n
have the value
attribute, because C passes the scalar objects by value. Regarding the character array, it is described in the interface as a flat 1D array of individual characters, because this is how the C side sees it with the char*
declaration.
On the C side you don't have a lot of changes. char*
instead of char**
, and &arr[i*len]
instead of arr[i]
: for, to address the i-th string of the Fortran array, you have to address the (len*i)-th character in C.
#include <cstring>
#include <algorithm>
using namespace std;
void ConvertToFortran(char* fstring, size_t fstring_len, const char* cstring)
{
size_t inlen = strlen(cstring);
size_t cpylen = min(inlen, fstring_len);
fill(fstring, fstring + fstring_len, ' ');
copy(cstring, cstring + cpylen, fstring);
}
extern "C"
{
void get_string_array(char* arr, int len, int n)
{
const char* strings[] = {"duma1", "duma2", "duma3"};
for (int i = 0; i < n; i++) {
ConvertToFortran(&arr[i*len], (size_t)len, strings[i]);
}
}
}