代码之家  ›  专栏  ›  技术社区  ›  Jamison Dance

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

  •  0
  • Jamison Dance  · 技术社区  · 15 年前

    我将一个中型(10000行)程序用C编写成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+ 如果我理解正确,我不需要 extern "C" {}; 围绕着我包含的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 回复  |  直到 15 年前
        1
  •  2
  •   Omnifarious    15 年前

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

    尝试将呼叫更改为 BWTRestoreBWT 这意味着要调用C函数 ::BWTRestoreBWT 在你的代码中,看看会发生什么。对呼叫执行相同操作 GetMatches .

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

        2
  •  2
  •   Anycorn    15 年前

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

    nm file.o | grep BWTRestoreBWT
    

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

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

        3
  •  2
  •   Michael Burr    15 年前

    我越是考虑这个问题,类声明中声明的函数看起来就越像,但是函数没有相应的定义。

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

    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
    }
    

    由于你原来问题中的错误,我只能假设 BWTrStReBubWT() 在里面 BWAGenome.h 在里面 半规管类 ,像这样:

    class BWAGenome {
        // etc...
    
        static bwt_t * BWTRestoreBWT(const char *fn);
    
        // etc...
    };
    

    这意味着 BWTrStReBubWT() 是一个成员 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
    }
    

    或者你可以移动的声明 BWTrStReBubWT() 在外面 半规管类 (更正式地称为“命名空间范围”)。

    这样可以修复当前的链接器错误。如果您现在得到一个关于类似于 bwt_restore_bwt 找不到,你就会知道你需要做什么 外部“C” 对于C函数也是如此。

        4
  •  1
  •   xtofl Adam Rosenfield    15 年前

    你告诉链接器在哪里可以找到包含 BWAGenome::BWTRestoreBWT 功能?由于您单独编译所有内容,所以必须显式链接输出.o文件。

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

    1. 有一个对漂亮名字的定义,但你没有给链接器
    2. 您给链接器的对象文件不包含方法,也就是说,您没有实现它(或者认为您实现了,但给了实现一个“错误”的名称)。
        5
  •  1
  •   Anycorn    15 年前

    如果将静态关键字与非类成员函数一起使用,则该函数将具有本地链接,这意味着它在编译单元(即.cpp文件)之外将不可见。 您要么获取静态关键字,要么将函数体放入include文件中。

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

        6
  •  0
  •   wallyk    15 年前

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

    它在找 BWAGenome::BWTRestoreBWT(char const*) 但是也许你有 BWAGenome::BWTRestoreBWT(char *) (没有) const )改为声明?

        7
  •  0
  •   Jamison Dance    15 年前

    错误发生在我将对象文件链接到一起的顺序上。我需要先链接C代码,然后再链接我创建的bhagenome类来调用它。链接器找不到C代码符号,因为它们尚未链接。不过,谢谢你的帮助。我想我让一些人失望了,但无论如何还是要谢谢你。