SDL with C++ calling Fortran: Scope and Initializer error

190 views Asked by At

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?

1

There are 1 answers

5
Vladimir F Героям слава On BEST ANSWER
extern "C++" void __stdcall callSomeFortran_();

is wrong.

  1. You declared it in Fortran as

    callSomeFortran() bind(C)
    

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 as bind(C,name="callSomeFortran")

  1. I don't see any reason for __stdcall, I think you are using the default calling conventions.

  2. It should be extern "C"{}, not "C++". You want it to have C linkage.

Both extern "C" and bind(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 as value.

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.