使用g ++编译C和C ++代码时链接错误

时间:2009-12-12 06:42:26

标签: c++ c linker-errors

我正在将用C编写的中型(10,000行左右)程序集成到C ++程序中。我创建了一个新类BWAGenome作为C代码的接口,因此封装了对C函数的任何访问。我正在使用g++编译器编译所有内容。 .o文件都是正确生成的,但是当我尝试将它们链接到最终的可执行文件时,编译器会抱怨它找不到符号。这是我收到的错误消息:

Undefined symbols:
BWAGenome::BWTRestoreBWT(char const*)", referenced from:
  BWAGenome::BWAGenome(char const*)in BWAGenome.o
"BWAGenome::GetMatches(unsigned int, int, bwt_t*, bwt_t*, bwt_t*, bntseq_t*, bntseq_t*)", referenced from:
  BWAGenome::getMatches(unsigned int, int)in BWAGenome.o

这些函数都在我制作的C ++类中。它们将函数包装在C代码中,但我完全不了解这些符号是如何定义的。

关于代码的一些细节以及我到目前为止所做的工作:

  • 所有内容都使用g++进行编译,因此,如果我理解正确,我不需要围绕我包含的c头文件extern "C" {};
  • 所有代码都单独正确编译。错误仅在链接期间发生。
  • 我听说某个地方可能需要从静态函数调用C代码,所以我尝试将每个调用包装到静态类方法中的C函数并调用它。

关于如何解决这个问题的任何想法?

<小时/> 编辑:添加BWTRestoreBWT和GetMatches

的定义和声明
//definition in BWAGenome.h
static bwt_t * BWTRestoreBWT(const char *fn);

//declaration in BWAGenome.cpp
static bwt_t * BWTRestoreBWT(const char *fn) {
    return bwt_restore_bwt(fn);
    //bwt_restore_bwt is a function in the C code that I am attempting to integrate
}

第二次编辑:经过多次灵魂搜索后,我意识到这个问题与我认为的大部分内容完全无关。有关详细信息,请参阅我的回答。

7 个答案:

答案 0 :(得分:2)

我注意到它正在寻找BWAGenome::BWTRestoreBWTBWAGenome::GetMatches。这些是它寻找的成员函数,而不是根命名空间全局自由函数。

尝试将要调用C函数的BWTRestoreBWT调用更改为代码中::BWTRestoreBWT的调用,看看会发生什么。对GetMatches的通话也一样。

那个告诉你需要从静态C ++函数调用C函数的人是错误的。这将迫使你将标准库包装在C ++静态函数中,这很愚蠢。

答案 1 :(得分:2)

尝试使用nm程序获取程序中定义和引用的符号输出:

nm file.o | grep BWTRestoreBWT

您应该看到带有T或U的符号.T表示名称已定义,后者表示符号未定义但被调用。为了链接,每个U必须有相应的T。

确保您的函数没有内联限定符,除非它们在头文件中定义。

答案 2 :(得分:2)

我对这个问题的思考越多,看起来你的类声明中声明的函数越多,但你没有相应的函数定义。

例如,此示例编译得很好,但会产生您看到的相同链接器错误:

typedef unsigned int bwt_t;
typedef unsigned int bntseq_t;

class BWAGenome {
public:
    BWAGenome( char const* name);

    void BWTRestoreBWT( char const* name);

    void GetMatches( unsigned int, int, int, bwt_t*, bwt_t*, bwt_t*, bntseq_t*, bntseq_t*);
    void getMatches( unsigned int, int);

};

BWAGenome::BWAGenome( char const* name) 
{
    BWTRestoreBWT( name);
}

void BWAGenome::getMatches( unsigned int x, int y)
{
    GetMatches( x, y, 0,0,0,0,0,0);
}

int main()
{
    return 0;
}

函数BWTRestoreBWT()GetMatches()应该是class BWAGenome的一部分还是被包装的C函数?如果是后者,则表明您将这些函数的头部包含在错误的位置(事实上,它们可能需要添加extern "C"链接规范)。


编辑以回应问题中的新信息:


在您编辑的问题中,您说:

//definition in BWAGenome.h
static bwt_t * BWTRestoreBWT(const char *fn);

//declaration in BWAGenome.cpp
static bwt_t * BWTRestoreBWT(const char *fn) {
    return bwt_restore_bwt(fn);
    //bwt_restore_bwt is a function in the C code that I am attempting to integrate
}

由于原始问题中存在错误,我只能假设BWTRestoreBWT()BWAGenome.h的声明位于class BWAGenome内,如此:

class BWAGenome {
    // etc...

    static bwt_t * BWTRestoreBWT(const char *fn);

    // etc...
};

这意味着BWTRestoreBWT()class BWAGenome()的成员,因此其定义应如下所示(请注意BWAGenome::作用域操作符):

//declaration in BWAGenome.cpp
static bwt_t * BWAGenome::BWTRestoreBWT(const char *fn) {
    return bwt_restore_bwt(fn);
    //bwt_restore_bwt is a function in the C code that I am attempting to integrate
}

或者您可以将BWTRestoreBWT()的声明移到class BWAGenome之外(更正式地称为“命名空间范围”)。

那应该修复你当前的链接器错误。如果您现在收到有关名称类似于bwt_restore_bwt但未找到的内容的错误,那么您也知道您需要为C函数执行extern "C"

答案 3 :(得分:1)

您是否告诉链接器在哪里可以找到包含BWAGenome::BWTRestoreBWT函数的库/对象?由于您单独编译所有内容,因此必须明确链接输出.o文件。

可能导致此链接错误的两个原因是

  1. 有一个名称的定义,但你没有将它提供给链接器
  2. 您为链接器提供的目标文件不包含该方法 - 即您没有实现它(或者您认为已经实现了,但为实现提供了'错误'的名称)

答案 4 :(得分:1)

如果将static关键字与非类成员函数一起使用,该函数将具有本地链接,这意味着它不会在编译单元外部显示,即.cpp文件。 你要么必须得到静态关键字,要么将函数体放入你的包含文件中。

在类成员函数的上下文中,static具有不同的含义。在这种情况下,static允许在不实例化类对象的情况下调用函数。

答案 5 :(得分:0)

您是否检查过您确实声明了相同形状的功能?

它正在寻找BWAGenome::BWTRestoreBWT(char const*),但您可能会声明BWAGenome::BWTRestoreBWT(char *)(没有const)吗?

答案 6 :(得分:0)

错误是我将目标文件链接在一起的顺序。我需要首先链接C代码,然后我创建的BWAGenome类来调用它。链接器找不到C代码符号,因为它们尚未链接。谢谢你的帮助。我想我有些人感到沮丧,但不管怎样,谢谢。