简体   繁体   中英

Multiple definition of main: linking fortran with C++

I would like to write a C++ program that calls the mvndst_() subroutine from

http://www.math.wsu.edu/faculty/genz/software/fort77/mvndstpack.f

On Linux, if I create test.cc:

extern "C" {
    int mvndst_(int *, double *, double *, int *, double *, int *,
                double *, double *, double *, double *, int *);
};
int main() {
    return 0;
}

and compile via

g++ -c -o test.o test.cc
gfortran -c -o mvndstpack.o mvndstpack.f
gfortran -Mnomain -o test test.o mvndstpack.o

then I get

mvndstpack.o: In function `main':
mvndstpack.f:(.text+0x4a2a): multiple definition of `main'
test.o:test.cc:(.text+0x0): first defined here
collect2: ld returned 1 exit status

However, if I run strip -N main mvndstpack.o prior to linking, then the linking succeeds. Can someone explain why the -Mnomain flag did not work here? I'd also like to avoid a solution that uses "strip" since the behavior of "strip" on Mac OS X appears to be different (ie, the -N option is not available, and I'm not sure of another way to obtain the right behavior). I'd also like to avoid editing the original Fortran source, if possible.

Details: - GNU Fortran (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 - g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 - GNU strip (GNU Binutils for Ubuntu) 2.21.53.20110810 - strip on Mac OS X 10.6 Snow Leopard

I can't find any documentation for the -Mnomain option, but gfortran doesn't complain about it (it seems to pass it on to the linker). But it also didn't complain when I ran

gfortran -Mnoplatypus -o test test.o mvndstpack.o

So my guess is that it doesn't support -Mnomain , and that it's being silently ignored. (Either that, or there's a -Mnoplatypus option, but that hardly seems likely.)

What worked for me was to comment out the PROGRAM TSTNRM .. END lines in mvndstpack.f (lines 15 through 62).

That's probably the most sensible approach anyway; you don't want to use the Fortran main program, so you might as well not compile it, rather than trying to trick the linker into ignoring it.

(If you prefer, you can use #if ... #endif or #ifdef ... #endif .)

EDIT:

Since your main program is in C++, you probably need to use g++ , not gfortran , to create the executable:

g++ -c -o test.o test.cc
gfortran -c -o mvndstpack.o mvndstpack.f
g++ -o test test.o mvndstpack.o

(And at some point you'll actually want to call the function.)

Your problem is the FORTRAN code you have includes a main as well, just in that world it is known as PROGRAM . From mvndstpack.f :

      PROGRAM TSTNRM
*
*     Test program for MVNDST
*

You need to pick which side of the fence is going to host the party first!

In this case you want the C++ to call the FORTRAN, therefore you just need to ditch the top part of the FORTRAN file which contains the TSTNRM program, or wrap it in a conditional compilation section:

#if TEST
      PROGRAM TSTNRM
...
      END
#endif

You can then rename the file to (case matters) mvndstpack.F or mvndstpack.FPP , or use -cpp on the command line options to gfortran.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM