Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28456 Discussions

Calling a C++ function and returning a string

Fett__Sebastian
Beginner
625 Views

Hello,

I wanted to encrypt a few files generated by my Fortran code and decided to use a c++ library for that.

As long as I stay inside my c++ part everything works fine but saving the decrypted file and then opening it in Fortran after the c++ part is done is not efficient therefore I wanted to pass the result directly.

From what I've read I need to pass the length of the string (-1 for the \0) as well as the address of it.

Passing the int part works perfectly fine but I cannot seem to pass the address nor a pointer. I tried passing the address as an int but that seems completly dirty (might be easier though)

 

My Fortran code is:
 

subroutine Encryption()
use, intrinsic :: ISO_C_BINDING
#include "test_api.h"
type(c_ptr) :: strptr=C_NULL_ptr
integer::strlen
character(c_char), pointer::textptr
call encrypt("smalltestfile.txt","finished.txt")
call decrypt("finished.txt", strptr, strlen)
call c_f_pointer(strptr, textptr, shape=[strlen-1])
write(*,*) associated(textptr)

 

My Fortran Interface is:

INTERFACE
   SUBROUTINE encrypt(UCV,RCV) BIND(C, name="encrypt")
      USE, INTRINSIC :: ISO_C_BINDING
      character(*), intent(in) :: UCV, RCV
   END SUBROUTINE
   
   SUBROUTINE decrypt(UCV, strptr, strlen) BIND(C, name="decrypt")
      USE, INTRINSIC :: ISO_C_BINDING
      character(*), intent(in) :: UCV
      type(C_PTR), value::strptr
      integer(c_int), intent(out):: strlen
   END SUBROUTINE
END INTERFACE

 

And the minimized C++ part to just test how to return a string:

void decrypt(char **a, const char **strptr, int *strlen) {
filename =  *a;
const char* test = "12345";
 strptr = &test
*strlen = 15;
return;
}

 

Now my associated tells me that the fortran pointer is (T) associated with a pointer. No idea how to properly access the values there now.

I am not used to C++ or Fortran so if I have some fundamental mistake I apologize ahead. Only programmed Python and JS before moving to this project for quite some time.

I've tried reading and understanding https://software.intel.com/en-us/node/749209 as this seems very close to what I wanted to do, but wasnt able to adapt it to my code.

Thanks in advance

0 Kudos
1 Reply
FortranFan
Honored Contributor II
625 Views

@Fett, Sebastien:

Look into the standard features in Fortran toward interoperability with C and make use of that in your C++ code using extern "C":

https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-standard-fortran-and-c-interoperability

Here'a quick example.

C++ function:

#include<string>
#include "ISO_Fortran_binding.h"
using namespace std;

extern "C" {
   void Fstring( CFI_cdesc_t *, int * );
}

void Fstring( CFI_cdesc_t *Fstr, int *ret ) {

   std::string s = "Hello World! The feature involving enhanced interoperability with C in the Fortran standard can be useful.";
   *ret = CFI_allocate(Fstr, (CFI_index_t *)0, (CFI_index_t *)0, s.length());
   if ( *ret == 0 ) {
      std::memcpy( Fstr->base_addr, s.c_str(), s.length() );
   }
   return;

}

Fortran main program:

   use, intrinsic :: iso_c_binding, only : c_char, c_int

   interface
      subroutine Fstring( str, irc ) bind(C, name="Fstring" )
      ! C++ function prototype:
      ! extern "C" {
      !    void Fstring( CFI_cdesc_t *, int * );
      ! }

         import :: c_char, c_int

         ! Argument list
         character(kind=c_char,len=:), allocatable, intent(out) :: str
         integer(c_int), intent(inout)                          :: irc

      end subroutine
   end interface

   ! Local variables
   character(kind=c_char,len=:), allocatable :: s
   integer(c_int) :: irc

   call Fstring(s, irc)
   print *, "C++ function Fstr returned: "
   print *, s

end

Upon compilation and linking using a supported C++ compiler and Intel Fortran and linker tool should produce the following output upon execution of the program:

 C++ function Fstr returned:
 Hello World! The feature involving enhanced interoperability with C in the Fort
 ran standard can be useful.

See some other threads you may find useful:

https://software.intel.com/en-us/forums/intel-fortran-compiler/topic/734563

https://software.intel.com/zh-cn/node/808879

https://software.intel.com/en-us/forums/intel-fortran-compiler/topic/815905

 

0 Kudos
Reply