3

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.

18
  • 1
    You need to establish on which side of the fence the error is occuring, whether it is in Fortran or C++. The C++ code by itself has nothing wrong with it provided that the pointers are valid and there is room to copy the characters into the buffer. Commented Sep 24, 2024 at 11:52
  • Are you certain that the array is represented as char*[3] and not as char[3][100]? In the latter case, you would receive a char* pointer pointing to a contiguous array of 300 characters. Commented Sep 24, 2024 at 11:59
  • 1
    Is there a particular constraint you have which means you can't use the language interoperability features defined by Fortran? If you are relying on implementation-specific methods then you will need to provide us substantially more detail about the implementations and systems you are using. Commented Sep 24, 2024 at 12:13
  • 1
    The first crucial thing is that you should be implementing the interactions between languages using C-interoperable interfaces ("bind(C)") and the second is to work out what the interoperable things are. If you can write using C interop with a clear statement of design goals, we'll be able to give more concrete advice. Commented Sep 24, 2024 at 13:07
  • 1
    Without trying to debug your code myself, I'd wonder whether you need pass-by-value for len and n. (Again: bind(C).) Commented Sep 24, 2024 at 13:14

1 Answer 1

6

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]);
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much your detailed implementation! I really appreciate what you provided, which of course works well. Hopefully this will be helpful for those who would like to see a simple example in this topic.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.