C / C ++, FORTRAN, underscores, and GNU Autotools

I have a question about programming in a mixed language (C / C ++ and FORTRAN) using gcc and gfortran. I searched for a lot of "mixing fortran with X language" and couldn't resolve it.

I'm not sure if this is a binding problem or a problem with the compiler, or both.

I created three files and I use GNU Autotools to create a rude application, but should be able to create an application from a line command independently.

The C file (main.c) will be the driving application that calls several FORTRAN Functions:

/* this is a simple program */ #include <stdio.h> /* add the extern function definition */ #include "fooonly.h" // this is not working for the mixed language programming stuff yet... /* this is the main program section */ int main( int argc, char *argv[] ) { int a = 36; int b = 24; int c = 0; printf( "hi mom\n" ); /* now call a FORTRAN function from C */ c = NGCD( &a, &b ); printf( "NGCD(%d,%d)=%d\n", a, b, c ); return 0; 

}

The fortran function, which will most often contain FORTRAN 77 (but may also contain the code FORTRAN90 / 95), looks like this:

 c$$$ The following introductory example in FORTRAN 77 finds the c$$$ $ greatest common divisor for two numbers A and B using a c$$$ $ verbatim implementation of Euclid algorithm. FUNCTION NGCD(NA, NB) IA = NA IB = NB 1 IF (IB.NE.0) THEN ITEMP = IA IA = IB IB = MOD(ITEMP, IB) GOTO 1 END IF NGCD = IA RETURN END 

Using Dev. Studio 6 / Compaq Digital Fortran 6.0, this works great. In fact, I don't need to use #define ifdef __cplusplus / # endif and can just create a C file that looks like this:

 /* this is a simple program */ #include <stdio.h> /* add the extern function definition */ extern "C" int __stdcall NGCD( int *a, int *b ); /* this is the main program section */ int main( int argc, char *argv[] ) { int a = 36; int b = 24; int c = 0; printf( "hi mom\n" ); /* now call a FORTRAN function from C */ c = NGCD( &a, &b ); printf( "NGCD(%d,%d)=%d\n", a, b, c ); return 0; } 

and compile it with the FORTRAN list above, application links, launches and generates the correct results.

 C:\fooonly>fooonly.exe hi mom NGCD(36,24)=12 C:\fooonly> 

When I try to repeat this process using GNU Autotools on MinGW or OSX, I continue to receive the following errors:

 macbook:makecheck $ make gcc -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"fooonly\" -DVERSION=\"1.0.2\" -I. -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c mv -f .deps/main.Tpo .deps/main.Po gfortran -g -O2 -o fooonly main.o ngcd.o Undefined symbols for architecture x86_64: "_NGCD", referenced from: _main in main.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status make: *** [fooonly] Error 1 macbook:makecheck $ 

where the Makefile (generated by GNU Autotools) basically contains the following commands:

 macbook:makecheck $ gcc -c main.c macbook:makecheck $ gfortran -c ngcd.f macbook:makecheck $ gcc -o fooonly main.c ngcd.o Undefined symbols for architecture x86_64: "_NGCD", referenced from: _main in cc9uPBWl.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status macbook:makecheck $ 

My configure.in script contains no more than:

 AC_INIT(main.c) AM_INIT_AUTOMAKE(fooonly, 1.0.2) ## C/C++ compiler section AC_PROG_CC ## fortran section AC_PROG_F77 ## output section AC_OUTPUT(Makefile) 

essentially

 macbook:makecheck $ gcc -c main.c macbook:makecheck $ gfortran -c ngcd.f macbook:makecheck $ gcc -o fooonly main.c ngcd.o 

right?

I am trying to build it on several platforms (Linux, Win32 / 64, OSX, etc.) and want to use GNU Autotools, and I know that this is done with other open source projects, but configure.in scripts are for those The projects are far superior to my GNU Autotools beginners, and I get a bit overloaded trying to decode them.

I assume this has something to do with:

1) The definitions that I used in the configure.in script, 2) I do not include a magic set of switches (i.e. -fno-second-underscore?), Or 3) Some combination of the two?

I close, and if so, how do I get the build application?

+3
source share
2 answers

While you have a compiler, but the last few years, I recommend using the ISO C binding to mix Fortran with other languages. You can then skip the name mangling with underscores and similar problems with the compiler and platform. If you have legacy FORTRAN 77 code that you don’t want to change, you can write a small Fortran 2003 gluing procedure between C and FORTRAN 77. The older instructions describe the previous method, which required a greater understanding of the internal interfaces and was more compiler / platform dependent. We will look at the new method in the chapter of the gfortran manual "Programming a mixed language" and previous questions / answers.

Fortran code is easier to link to gfortran because it includes Fortran runtime libraries. I think the same thing applies to C ++, so if you have both, you will have to explicitly include the runtime library of one or the other.

PS The following is an example of using Fortran ISO bindings:

 function NGCD (na, nb) bind (C, name="NGCD") use iso_c_binding implicit none integer (c_int) :: ngcd integer (c_int), intent (in) :: na, nb integer (c_int) :: ia, ib, itemp ia = na ib = nb do while (ib /= 0) itemp = ia ia = ib ib = mod(itemp, ib) end do ngcd = ia return end function NGCD 

Compile / Link to:

 gcc -c main.c gfortran main.o ngcd.f90 
+4
source

I did not have a sufficient answer, so I put together a workaround (ignores case in the FORTRAN code) and posted it on the forufus blog. In the future I will have to develop compiler keys.

-1
source

Source: https://habr.com/ru/post/1389299/


All Articles