I want to call a calculation from an older Fortran program but show me the results in a C++-SDL-routine.
Now I have read all the questions here concerning that, but somehow after following all regulations I still get compiler errors.
The relevant code-snippets are as follows:
SDL_wrapper.h:
extern "C++" void __stdcall callSomeFortran_();
SDL_wrapper.cpp:
#include "/usr/include/SDL/SDL.h"
#include "/usr/include/SDL/SDL_image.h"
#include <stdio.h>
#include "SDL_wrapper.h"
using namespace std;
int main(int argc, char *argv[])
{
callSomeFortran();
SDL_Surface *screen;
(...)
fortranFunctions.f90:
subroutine callSomeFortran() bind(C)
use iso_c_binding
implicit none
write(*,*) 'Were in Fortran!'
end subroutine callSomeFortran
Now when I don't call callSomeFortran()
in main, I can perfectly compile with
makefile
FLAGS = -lSDL -lstdc++
fortranFunctions: fortranFunctions.o wrapper.o
gfortran -o fortranFunctions wrapper.o fortranFunctions.o $(FLAGS)
fortranFunctions.o: fortranFunctions.f90
gfortran -c fortranFunctions.f90 -ffree-line-length-none -o fortranFunctions.o
But as I of course want to call that function I include it and get the following errors:
In file included from SDL_wrapper.cpp:5:0:
SDL_wrapper.h:1:29: error: expected initializer before ‘callSomeFortran_’
SDL_wrapper.cpp: In function ‘int main(int, char**)’:
SDL_wrapper.cpp:20:20: error: ‘callSomeFortran’ was not declared in this scope
I really don't get it. From all the previous posts I've studied, this should work. Also I've already some years coding experience and don't get where there should be a problem with scope.
Am I missing something obvious?
is wrong.
You declared it in Fortran as
the
bind(C)
means (not only) that no trailing underscore will be appended, you should not append it in C++ either. It is better to write it explicitly asbind(C,name="callSomeFortran")
I don't see any reason for
__stdcall
, I think you are using the default calling conventions.It should be
extern "C"{}
, not"C++"
. You want it to have C linkage.Both
extern "C"
andbind(C)
do a very similar thing. Force the procedure to follow simple C calling conventions. That means that for both Fortran and C++ that the symbol for the procedure will be the name of the function without any change. For Fortran it also means that all variables will be passed using a pointer to them unless declared asvalue
.Without
bind(C)
the name of the symbol would have_
appended, but this behaviour somewhat differs from compiler to compiler. Also, for module procedures it is more complicated.Without
extern "C"
the name of the symbol expected would be quite complicated and the rules are also not standardized.