Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
Welcome to the Intel Community. If you get an answer you like, please mark it as an Accepted Solution to help others. Thank you!
26758 Discussions

Calling a C++ function and returning a string

Fett__Sebastian
Beginner
195 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
195 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...

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

 

Reply