4

我想编写一个调用 mvndst_() 子例程的 C++ 程序

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

在 Linux 上,如果我创建 test.cc:

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

并通过编译

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

然后我得到

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

但是,如果我strip -N main mvndstpack.o在链接之前运行,则链接成功。有人可以解释为什么 -Mnomain 标志在这里不起作用吗?我还想避免使用“strip”的解决方案,因为 Mac OS X 上“strip”的行为似乎不同(即 -N 选项不可用,我不确定另一种方法获得正确的行为)。如果可能的话,我还想避免编辑原始的 Fortran 源代码。

详细信息: - 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 - Mac OS 上的 strip X 10.6 雪豹

4

2 回答 2

4

我找不到该-Mnomain选项的任何文档,但gfortran没有抱怨它(它似乎将它传递给链接器)。但我跑的时候它也没有抱怨

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

所以我的猜测是它不支持-Mnomain,并且它被默默地忽略了。(要么这样,要么有一个-Mnoplatypus选择,但这似乎不太可能。)

对我有用的是注释掉(第 15 到 62 行)中的PROGRAM TSTNRM..END行。mvndstpack.f

无论如何,这可能是最明智的方法。你不想使用 Fortran 主程序,所以你最好不要编译它,而不是试图欺骗链接器忽略它。

(如果您愿意,可以使用#if ... #endif#ifdef ... #endif。)

编辑:

由于您的主程序是 C++,您可能需要使用g++,而不是gfortran创建可执行文件:

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

(在某些时候,您实际上会想要调用该函数。)

于 2011-10-17T01:27:12.340 回答
2

您的问题是您拥有的 FORTRAN 代码也包含 a main,只是在那个世界中它被称为PROGRAM. 从mvndstpack.f

      PROGRAM TSTNRM
*
*     Test program for MVNDST
*

您需要先选择围栏的哪一侧来举办派对!

在这种情况下,您希望 C++ 调用 FORTRAN,因此您只需放弃包含TSTNRM程序的 FORTRAN 文件的顶部,或者将其包装在条件编译部分中:

#if TEST
      PROGRAM TSTNRM
...
      END
#endif

然后,您可以将文件重命名为(大小写)mvndstpack.Fmvndstpack.FPP,或-cpp在命令行选项上使用 gfortran。

于 2011-10-17T01:42:29.543 回答