向所有人致意。
我目前正在尝试使用UNIX中的GNU编译器(分别为g ++,gcc和f77)编译多语言程序(C,C ++和FORTRAN)。
我的所有来源都在编译成没有错误的对象但是我遇到了一个符号引用错误,因为它们的链接如下所示:
f77 -L/usr/sfw/lib -R/usr/sfw/lib -lgcc_s -o SlowDynamic.exe main.o \
SA.o mersenne.o CFE.o MA_57.o blas.o MA_57_Depend.o Metis.o\
BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o
NOTICE: Invoking /usr/bin/f90 -f77 -ftrap=%none -L/usr/sfw/lib -R/usr/sfw/lib -lgcc_s -o SlowDynamic.exe main.o SA.o mersenne.o CFE.o MA_57.o blas.o MA_57_Depend.o Metis.o BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o
Undefined first referenced
symbol in file
_Znwj SA.o
_ZNSt14basic_ofstreamIcSt11char_traitsIcEED1Ev SA.o
_ZNSt14basic_ofstreamIcSt11char_traitsIcEEC1Ev SA.o
_ZNKSsixEj main.o
_ZNSolsEPFRSoS_E SA.o
_ZNSt14basic_ofstreamIcSt11char_traitsIcEE4openEPKcSt13_Ios_Openmode SA.o
_ZNSolsEd SA.o
_ZNSolsEi SA.o
__cxa_end_catch SA.o
__cxa_begin_catch SA.o
_ZdlPv SA.o
_ZNSt14basic_ofstreamIcSt11char_traitsIcEE7is_openEv SA.o
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c SA.o
_ZSt4cerr SA.o
_ZSt4cout SA.o
_ZNSt14basic_ofstreamIcSt11char_traitsIcEE5closeEv SA.o
_ZNSt8ios_base4InitD1Ev main.o
_ZNSt8ios_base4InitC1Ev main.o
_ZNKSt9basic_iosIcSt11char_traitsIcEEntEv SA.o
__gxx_personality_v0 main.o
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc SA.o
__cxa_rethrow SA.o
_ZNKSs4sizeEv main.o
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ SA.o
ld: fatal: Symbol referencing errors. No output written to SlowDynamic.exe
*** Error code 1
make: Fatal error: Command failed for target `SlowDynamic.exe'
使用以下Makefile:
products: SlowDynamic.exe
SlowDynamic.exe: main.o SA.o mersenne.o CFE.o BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o MA_57.o blas.o MA_57_Depend.o Metis.o
f77 -L/usr/sfw/lib -R/usr/sfw/lib -lgcc_s -o SlowDynamic.exe main.o \
SA.o mersenne.o CFE.o MA_57.o blas.o MA_57_Depend.o Metis.o\
BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o
main.o: main.cpp
g++ -c -o main.o main.cpp
SA.o: SA.cpp
g++ -c -o SA.o SA.cpp
mersenne.o: mersenne.cpp
g++ -c -o mersenne.o mersenne.cpp
CFE.o: CFE.c
gcc -c -o CFE.o CFE.c
MA_57.o: MA_57.f
f77 -c -o MA_57.o MA_57.f
blas.o: blas.f
f77 -c -o blas.o blas.f
MA_57_Depend.o: MA_57_Depend.f
f77 -c -o MA_57_Depend.o MA_57_Depend.f
Metis.o: Metis.f
f77 -c -o Metis.o Metis.f
BCs.o: BCs.c
gcc -c -o BCs.o BCs.c
EMatrix.o: EMatrix.c
gcc -c -o EMatrix.o EMatrix.c
Numbering.o: Numbering.c
gcc -c -o Numbering.o Numbering.c
KMatrix.o: KMatrix.c
gcc -c -o KMatrix.o KMatrix.c
Solve.o : Solve.c
gcc -c -o Solve.o Solve.c
clean:
rm *.o Main.exe *.gpi
我已经读过这通常是缺少库的错误。我知道C& FORTRAN代码编译时(包括各自的库)和C ++代码一样编译。这让我相信它是导致错误的两个程序之间的接口。不幸的是,我几乎没有经验调试这类问题,没有任何来自链接器的线索,它很难向前发展。我将包含我的程序的必要部分,用于处理程序双方之间的接口。
首先是C ++部分:SA.h,SA.cpp
SA.h:
class SimAnneal {
...
std::vector<float> DensityArray;
std::vector<float> EnergyArray;
public
double ObjFunction ();
...
}
SA.ccp:
#include <math.h>
#include <iostream>
#include <fstream>
#include <time.h>
#include <vector>
#include "SA.h"
#include "CFE.h"
#include "randomc.h" //Includes mersenne.cpp
double SimAnneal::ObjFunction ()
{
CFE(&DensityArray[0], &EnergyArray[0]);
// sends pointers of both arrays to CFE.c and modifies EnergyArray as
// shown in CFE.c
double SumStrainEnergy = 0;
for (int i = 0; i < EnergyArray.size(); i++)
{
SumStrainEnergy += EnergyArray[i]; //Effectively sum of array
//engy[] from CFE.c
}
return SumStrainEnergy;
}
其次是C / FORTRAN部分:CFE.h,CFE.c
CFE.h:
#ifdef __cplusplus
extern "C" {
#endif
void CFE(float density[], float energy[]);
#ifdef __cplusplus
}
#endif
CFE.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "BCs.h"
#include "EMatrix.h"
#include "Numbering.h"
#include "KMatrix.h"
#include "fg_types.h"
#include "Solve.h"
void CFE(float density[], float energy[])
{
...stuff...
float * dens;
dens = density; //pass pointer of array density[0] in SA.cpp to CFE.c
...more stuff....
float * engy;
engy = energy; //pass pointer of array energy[0] in SA.cpp to CFE.c
***Modify engy in some respects****
}
本质上,SA.cpp中的ObjFunction在main.cpp中调用,其中包含main()。
有任何明显的错误吗?
有什么方法可以让链接器宣布链接中出现错误的原因/位置?
任何帮助都会很受欢迎。
谢谢。
+++编辑:详细反馈+++
birch $ g++ -v Hello.cpp
Reading specs from /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/specs
Configured with: /sfw10/builds/build/sfw10-patch/usr/src/cmd/gcc/gcc-3.4.3/configure --prefix=/usr/sfw --with-as=/usr/ccs/bin/as --without-gnu-as --with-ld=/usr/ccs/bin/ld --without-gnu-ld --enable-languages=c,c++ --enable-shared
Thread model: posix
gcc version 3.4.3 (csl-sol210-3_4-branch+sol_rpath)
/usr/sfw/libexec/gcc/sparc-sun-solaris2.10/3.4.3/cc1plus -quiet -v Hello.cpp -quiet -dumpbase Hello.cpp -mcpu=v7 -auxbase Hello -version -o /var/tmp//cc2JwHRb.s
ignoring nonexistent directory "/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../sparc-sun-solaris2.10/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../include/c++/3.4.3
/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../include/c++/3.4.3/sparc-sun-solaris2.10
/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../include/c++/3.4.3/backward
/usr/local/include
/usr/sfw/include
/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/include
/usr/include
End of search list.
GNU C++ version 3.4.3 (csl-sol210-3_4-branch+sol_rpath) (sparc-sun-solaris2.10)
compiled by GNU C version 3.4.3 (csl-sol210-3_4-branch+sol_rpath).
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Hello.cpp:6:2: warning: no newline at end of file
/usr/ccs/bin/as -V -Qy -s -xarch=v8 -o /var/tmp//ccvAshv7.o /var/tmp//cc2JwHRb.s
/usr/ccs/bin/as: Sun Compiler Common 10 Patch 09/04/2007
/usr/sfw/libexec/gcc/sparc-sun-solaris2.10/3.4.3/collect2 -V -R/usr/sfw/lib -Y P,/usr/ccs/lib:/usr/lib -Qy /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crt1.o /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crti.o /usr/ccs/lib/values-Xa.o /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crtbegin.o -L/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3 -L/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../sparc-sun-solaris2.10/lib -L/usr/ccs/lib -L/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../.. /var/tmp//ccvAshv7.o -lstdc++ -lm -R/usr/sfw/lib -lgcc_s -lgcc -lc -R/usr/sfw/lib -lgcc_s -lgcc -lc /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crtend.o /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crtn.o
ld: Software Generation Utilities - Solaris Link Editors: 5.10-1.490
答案 0 :(得分:4)
其中一些未定义的符号明显与标准C ++类(即ostream)有关。
您需要确保至少已连接C ++库(-lstdc ++)。
进一步调试:
使用单语言程序以详细模式(-v
)运行f77,g ++等,并查看编译器在每种语言的链接阶段自动包含哪些库
对于您自己的代码中的符号,使用nm
查看本机语言声明和非本机调用以确定它们不匹配的方式。关于下划线前缀等的规则是常用的。
(据我所知,但是自从我上次链接C和Fortran以来已有15年,C符号总是在内部以下划线为前缀,但Fortran符号不是)。
答案 1 :(得分:2)
主要问题是您正在使用F77编译器进行链接,默认情况下,该编译器不会链接到C ++标准库中。像Alnitak所说,在链接期间明确指定-lg ++来获取它。
此外,如果从C代码(或从F77代码)调用C ++函数,请确保将这些函数的原型包含在extern“C”{}块中,以便它们的符号名称显示在标准化的C中表单,而不是受损的C ++表单(这限制了你的某些东西,比如重载)。有关详细信息,请参阅here。
答案 2 :(得分:0)
通常,您应该将包含任何C ++代码的程序与C ++编译器链接,将Fortran和C库添加到链接行。此外,标准建议是使main()程序C ++,也不是Fortran,因为C ++的启动序列是不同的。将Fortran代码转换为从最小的C ++ main调用的函数。
int main(void) // Assuming no argument handling - probably incorrect
{
return(fortran_main_program());
}