开发者

Multiple definition of main: linking fortran with C++

开发者 https://www.devze.com 2023-04-13 05:08 出处:网络
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

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 (i.e., 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开发者_C百科.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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号