Default arguments for pointer in C++ and mixed programming

1.5k Views Asked by At

The usage of default arguments for pointers in C++ can be demonstrated with following code

#include <iostream>

void myfunc_(int var, double* arr = 0) {
  if (arr == 0) {
    std::cout << "1 arg" << std::endl;
  } else {
    std::cout << "2 arg" << std::endl;
  }
}

int main() {
  myfunc(1);
  double *arr = new double[2];
  myfunc(1, arr);
}

in this case, the output of the program is

1 arg
2 arg

on the other hand, if i try to pass optional arguments from Fortran to C++, it does not work. The following example code demonstrates the sutiation

The myfunc.cpp

#include <iostream>

extern "C" void myfunc_(int var, double* arr = 0) {
  if (arr == 0) {
    std::cout << "1 arg" << std::endl;
  } else {
    std::cout << "2 arg" << std::endl;
  }
} 

and the Fortran main program

program main
use iso_c_binding

real*8 :: arr(2)

call myfunc(1)
call myfunc(1, arr)
end program main

and the mixed code (Fortran and C++) can be compiled using following command without any error

g++ -c myfunc.cpp
gfortran -o main.x myfunc.o main.f90 -lstdc++ -lc++ 

but the program prints

2 arg
2 arg

in this case. So, Is there any solution for this problem? Am i missing something in here? I think that using default arguments in mixed programming is not working as it expected but i need suggestion at this point.

1

There are 1 best solutions below

6
Vladimir F Героям слава On BEST ANSWER

As pointed out in the comments, you cannot have default values of parameters in extern "C" functions. However, you can have optional arguments in the Fortran interface of the function and call it exactly the way you want:

#include <iostream>
extern "C" void myfunc(int var, double* arr) { //removed the = 0 and renamed to myfunc
  if (arr == 0) {
    std::cout << "1 arg" << std::endl;
  } else {
    std::cout << "2 arg" << std::endl;
  }
}

In Fortran create an interface describing the C(C++) function:

program main
use iso_c_binding

interface
  subroutine myfunc(var, arr) bind(C, name="myfunc")  
    use iso_c_binding
    integer(c_int), value :: var
    real(c_double), optional :: arr(*)
  end subroutine
end interface

!C_double comes from iso_c_binding
real(c_double):: arr(2)

call myfunc(1_c_int)
call myfunc(1_c_int, arr)
end program main

The key thing is the optional attribute in the interface. If you don't supply the optional array, a null pointer will be passed instead.

Also notice the value attribute to the var argument. It is necessary because the C++ function accepts the parameter by value.

Note: this is quite a recent addition as a TS to the Fortran 2008 standard, but is widely supported.