Prototype for calling Fortran function with a vector and two integers from C program

I have a C program that calls a Fortran function. I’m getting the below compiler error message. Can you give me examples on how to fix this with a C prototype?

error: implicit declaration of function ‘test_’ [-Werror=implicit-function-declaration]
`if (test_(&x, y, &z) != 0);`
      INTEGER FUNCTION TEST(A,B,C)
      REAL B(*)
      INTEGER A,B
      
      RETURN 
      END
int main ()
{
  int x;
  float y;
  int z;
  
  if (test_(&x, y, &z) != 0)
    printf ("Yes \n");
}
1 Like
$ gfortran -c test.f
$ gcc main.c test.o -o main
$ ./main
Yes 
C     test.f
C
      INTEGER(C_INT) FUNCTION TEST(A,B,C) BIND(C)
      USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_FLOAT, C_INT
      REAL(C_FLOAT) B(*)
      INTEGER(C_INT) A, C ! note the error in your Fortran routine
      TEST = 42_C_INT
      RETURN 
      END
// main.c

#include <stdio.h>

int test(int *a, float *b, int *c); // missing declaration in your main program
                                    // no need for trailing underscore '_' due to
                                    // BIND(C) attribute on the Fortran side
int main()
{
  int x;
  float y;
  int z;
  
  if (test(&x, &y, &z) != 0)
    printf ("Yes \n");
}

Note the usage of BIND(C) as the standard way of overcoming compiler name mangling issues. You also won’t have to carry the trailing _ around anymore.

Putting a bit more effort into your minimal working example would go a long way.

In principle a compiler may choose to change the name mangling scheme between versions and render your code useless even on the same OS/compiler. Also if you put your procedure(s) in a module then the module name will probably be included in the name mangling and renaming the module would again break your code.

iso_c_binding is there to reduce clutter and errors, not the opposite.

2 Likes

The underscore at the end of your function call in main.c is the result of the name mangling scheme of your fortran compiler. Name mangling - Wikipedia

It’s not documented, but this might be the way gfortran currently does name mangling:

Current GFortran name mangling
------------------------------

Currently the name mangling is a bit ad-hoc, with several different
prefixes depending on which part of the compiler is used:

- Procedure "foo" in module "bar": __bar_MOD_foo

- Runtime library: _gfortran_XXX

- Runtime library internal functions (not visible if symbol visibility
  is supported): _gfortrani_XXX

- ISO_C_BINDING functions in the library: __iso_c_binding_XXX

- OOP stuff: __class_XXX

My, entirely personal, advice would be to “run, do not walk” from such a workplace.

The “ISO_C_BINDING stuff” is how Fortran talks to C and vice versa. Everything else is technical debt.

3 Likes