Passing strings to C(++) functions without copying

TL;DR

  • Let the “C descriptors” with the 2 processors of Fortran and the companion C one do most of the work for you i.e., seek Fortran 2018 facility to directly interoperate objects in Fortran wherever viable; this includes CHARACTER types with ALLOCATABLE (and POINTER) attributes.
  • Ensure interoperable types and this includes C_CHAR kind in Fortran objects of CHARACTER intrinsic type.

@plevold,

You may want to preview some of the suggestions I have long posted at this site (e.g., here) and/or Intel Fortran forum and comp.lang.fortran where I recommend further employment of the enhanced interoperability with C offered with Fortran starting the 2018 revision. Please note the ALLOCATABLE attribute in Fortran often comes in really handy, especially given Fortran’s rather nice safety features with this attribute when it comes to memory management.

Let us presume for a moment the “strings” you have in Fortran have the ALLOCATABLE attribute, a safer way to work with them given your attention in the original post with the “amount of data”. That is, as opposed to them being literal constants as your example shows.

In that case, you can even work with the deferred-shape option in Fortran and gain considerable brevity and simplicity with the interface:

#include <string_view>
#include <iostream>
#include "ISO_Fortran_binding.h"

extern "C" {
   void echo_c( const CFI_cdesc_t* Fstr )
   {
      auto view = std::string_view((char *)Fstr->base_addr).substr(0, Fstr->elem_len);
      std::cout << view << std::endl;
   }
}
   use, intrinsic :: iso_c_binding, only : c_char
   interface
      subroutine echo_c( str ) bind(C, name="echo_c" )
         import :: c_char
         ! Argument list
         character(kind=c_char, len=:), allocatable, intent(in) :: str
      end subroutine
   end interface
   character(kind=c_char, len=:), allocatable :: s
   s = c_char_"Hello World!"
   call echo_c( s )
end

Program behavior on WIndows using IFORT and Microsoft C/C++ companion processor:

C:\temp>cl /c /std:c++20 /EHsc /W3 c++.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.30.30706 for x64
Copyright (C) Microsoft Corporation. All rights reserved.

c++.cpp
C:\Program Files (x86)\Intel\oneAPI\compiler\latest\windows\compiler\include\ISO_Fortran_binding.h(156): warning C4200: nonstandard extension used: zero-sized array in struct/union
C:\Program Files (x86)\Intel\oneAPI\compiler\latest\windows\compiler\include\ISO_Fortran_binding.h(156): note: This member will be ignored by a defaulted constructor or copy/move assignment operator

C:\temp>ifort /c /standard-semantics p.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.5.0 Build 20211109_000000
Copyright (C) 1985-2021 Intel Corporation. All rights reserved.

C:\temp>link p.obj c++.obj /subsystem:console /out:p.exe
Microsoft (R) Incremental Linker Version 14.30.30706.0
Copyright (C) Microsoft Corporation. All rights reserved.

C:\dev\temp>p.exe
Hello World!

1 Like