2
votes

One colleague did send me a Fortran function to include in my C++ program. So far, everything in my program is coded in C++. To keep things simple (especially dependencies and installation) I thought I'll just re-code it in C++. Unfortunately, the code is very complex with many goto statements and other stuff I'm not very familiar with. (I have never worked with Fortran and this is from an old scientific Fortran 77 program)

Thus, I would like to call the Fortran function directly in C++. A prerequisite is, that I'm using CMake for my program and everything (like linking) has to be done in the CMake file. Additionally, the CMake file should be as simple as possible since only scientists work and extend the program with no sophisticated programming background.

I found many approaches and solutions on the internet - however, most are very complex dealing with modules and libraries - I only need to call one function, we are not working with libraries or such.

Unfortunately, I get a lot of errors when executing my code:

c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible C:/MinGW/lib/gcc/mingw32/6.3.0/libgfortran.dll.a when searching for -lgfortran c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible C:/MinGW/lib/gcc/mingw32/6.3.0/libgfortran.a when searching for -lgfortran c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible C:/MinGW/lib/gcc/mingw32/6.3.0\libgfortran.a when searching for -lgfortran c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible C:/MinGW/lib/gcc/mingw32/6.3.0/libgfortran.dll.a when searching for -lgfortran c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: skipping incompatible C:/MinGW/lib/gcc/mingw32/6.3.0/libgfortran.a when searching for -lgfortran c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lgfortran

My main question is: Are these errors due to a problem in my code or are they related to a problem with my environment?

This is what my code looks like:

main.cpp

#include <iostream>

extern double f_add(double *, double *, double *);

int main() {
    double a = 1.;
    double b = 2.;
    double c;
    f_add(&a, &b, &c);

    std::cout << c << std::endl;
}

f_add.f

  real function f_add(a, b, c)
  real a,b,c
  c = a+b
  end

CMakeLists.txt

cmake_minimum_required(VERSION 3.17)
project(test_cpp)

set(CMAKE_CXX_STANDARD 14)
SET (CMAKE_Fortran_COMPILER  gfortran)
ENABLE_LANGUAGE(Fortran)

set(SOURCE_FILES
        main.cpp
        f_add.f
        )

add_executable(test_cpp ${SOURCE_FILES})
1
How does the actual linking command look like? What is your C++ compiler version? What is your Fortran compiler version? Which flags do they use?Vladimir F
It looks like you have g++ 9.2.0 and gfortran 6.3.0. It may help to ensure that you are using the same version for each. (It's also likely that you may have trouble matching real and double when you do manage to get something built.)francescalus
thus an idea would be to uninstall MinGW and install it again?user7431005
ok, installing MinGW new worked - kind of. Now I'm getting an undefined reference to f_add... erroruser7431005
@francescalus since this solved my problem you can make it an answer. I need to ask another question with the new error message nowuser7431005

1 Answers

2
votes

I think your C++ code is missing extern "C" and some additional corrections to the Fortran code. For example, the following would work:

#include <iostream>
extern "C" {
    double f_add(double, double);
}
int main() {
    double a = 1.;
    double b = 2.;
    double c;
    c = f_add(a, b);
    std::cout << c << std::endl;
}

and,

function f_add(a, b) result(c) bind(C, name = "f_add")
    use iso_c_binding, only: c_double
    implicit none ! remove this line if your F77 code has implicitly-declared variables.
    real(c_double), intent(in), value   :: a, b
    real(c_double)                      :: c
    c = a + b
end function f_add

Then compile, link, and run (via MinGW GNU 10.1 that I am using),

gfortran -c f_add.f90
g++ -c main.cpp
g++ *.o -o main.exe
./main.exe

The output is,

3

I do not have CMake installed in MinGW, but setting it up should be straightforward with the above modifications. Your CMake file is fully functional in a Linux environment if that helps.