I am trying to call a C++ function in a Fortran subroutine. This C++ function is supposed to update an integer array. Here is a non-working code I wrote. What is the issue?
! Fortran function that calls a C++ function.
subroutine my_function()
      integer(4) ar(*)
      integer(4) get_filled_ar
      ! Need correct syntax here.
      ar = get_filled_ar()
end
// C++ function:
    extern "C" {
        void get_filled_ar(int *ar){
            ar[0] = 1;
            ar[1] = 10;
            ar[3] = 100;
        }
    }
                With Fortran 2003 there is a standard and thus platform and compiler independent way to call C from Fortran, and also any language that uses the C calling interface. Also to call Fortran from C. While the various compiler writers are gradually adding Fortran 2003 features and there are few complete 2003 compilers, the ISO C Binding has been available for some time in many compilers. The ISO C Binding works better than the previous ad hoc techniques, which were sometimes poorly documented, and varied between compilers and platforms. To call C from Fortran, you write an "interface" that tells the Fortran compiler that it should use the C calling conventions, and C types.
Here is an example. As Mike wrote, since the C++ function returns void, treat it in the Fortran as a subroutine and call it. Thus it doesn't need to be given a type. Also, somewhere in the Fortran you have to reserve storage for the array -- the easiest way is with a declaration with numeric value for the dimension. And you need a main program in some language.
program test_call_C
use iso_c_binding
implicit none
interface c_interface
   subroutine get_filled_ar (ar) bind (C, name = "get_filled_ar")
   use iso_c_binding
   implicit none
   integer (c_int), intent (out), dimension (*) :: ar
   end subroutine get_filled_ar
end interface c_interface
integer (c_int), dimension (0:3) :: ar
call get_filled_ar (ar)
write (*, *) "Fortran: ar:", ar
stop
end program test_call_C
and in C:
void get_filled_ar (
   int ar []
) {
   ar [0] = 1;
   ar [1] = 10;
   ar [2] = 100;
   return;
}
Example commands:
gcc -c get_filled_ar.c
gfortran get_filled_ar.o test_call_C.f90  -o test_call_C.exe
./test_call_C.exe
To call your C++ code, use the following commands. The name specified in the "bind" obviates the need for a trailing underscore so your C++ code works directly.
g++ -c cplusplus.cc
gfortran cplusplus.o test_call_C.f90  -o test_call_Cplusplus.exe
./test_call_Cplusplus.exe
                        Here's a full program with your code in it that should work (at least on linux with gcc/gfortran).
In the fortran file fortran.f, put:
     IMPLICIT NONE      
     CALL my_function()
     END
! FORTRAN function that calls a C++ function
     subroutine my_function()
! Tell fortran about the C++ function:
       external get_filled_ar
       integer ar(4)
! As the C++ function returns void, call it as a subroutine in
! fortran:
       call get_filled_ar(ar)
! To check it worked, print out the numbers:
       do i = 1,4
          write(*,*) i,"->",ar(i)
       enddo
     end
In cplusplus.cc put:
extern "C"
{
  void get_filled_ar_(int* ar) // note extra underscore to keep linker happy
  {
    ar[0] = 1;   
    ar[1] = 10;
    ar[3] = 100;
  }    
}
Then build (on linux with gcc/gfortran, might be different on other systems) with:
gfortran -c fortran.f
gcc -c cplusplus.cc
gfortran -o program-name fortran.o cplusplus.o
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With