c ++未定义的<a function=""></a>引用

时间:2011-05-09 07:24:57

标签: c++ linux

HI,

我对c ++ / linux(ubuntu)中的.h文件和.cpp文件有一些疑问。

  1. 可以使用g ++编译.h文件,也可以编译包含.h文件的.cpp文件?

  2. 从.h文件和它的.cpp文件(.cpp,其中我包含一些代码到我在.h文件中定义的方法)我使用命令创建一个.so文件:

    g++-fPIC -shared my_code.cpp -o my_code.so`
    

    test.cpp我包含.h文件并使用dlopen我在.so文件上创建一个处理程序。为什么我有以下错误:

    undefined reference to bool `Class::method(std::string)` `collect2: ld returned 1 exit status
    
  3. 如果我在.h文件中说虚拟bool方法...编译test.cpp时没有错误。有人可以解释我做错了什么吗?问题是我有一个模板。使用模板我不能使用virtual..so..i有这个未定义的错误,我不知道如何解决它。 THX

  4. 编辑:

    当我编译my_code.cpp时,我有错误:

    /usr/bin/ld: .usr/lib/debug/usr/lib/crt1.o relocation 0 has invalid symbol index 12 (same with index 13,2,14...22 ).
    

    但是当我创建.so文件时,没有错误。我用:

    g++ test.coo -ldl -o test
    

    用于test.cpp编译。

2 个答案:

答案 0 :(得分:2)

广告1:可以编译.h文件(您可以明确覆盖语言检测),但您不想这样做。 .h文件旨在包含在内,不会编译为任何有用的文件。

广告2:您必须链接对照您创建的库,方法是传递-lmy_code(但请注意,要使其工作,您必须将其创建为libmy_code.so)以及适当的-L标志(放置libmy_code.so的目录)到链接器。像这样:

g++ test.cpp -L. -lmy_code -ldl -o test

但您还必须将第一个命令更改为:

g++ -fPIC -shared my_code.cpp -o libmy_code.so
                                 ^^^
                                 libraries *must* have `lib` prefix on unix systems.

并假设两者都在同一目录中完成 - 如果不是,则必须调整-L选项以指向libmy_code.so所在的目录。此外,您必须将libmy_code.so放置在动态链接器可以找到它的位置。通过安装它或将环境变量LD_LIBRARY_PATH设置到适当的目录。或者,您可以使用

进行编译
g++ test.cpp my_code.so -ldl -o test

这不会强制lib前缀,它会在二进制文件中创建一个“rpath”条目,因此它会在原始位置找到该库。

这一切都假设你想将它用作常规库,在这种情况下你不想使用dlopen dlopen用于在运行时将库作为插件打开,而只能通过使用dlsym()获取符号指针来访问它们,但是如果要正常访问库,则必须链接它以便链接器可以解析符号。

如果您想使用dlopen,则不得在my_code.h中包含 test.cpp不得使用任何内容除了通过dlsym获取符号之外,定义。因为这是C ++,它反过来要求你理解符号修改方案,因为dlsym不会为你做这个。

答案 1 :(得分:0)

  1. 通常不需要编译.h文件,它只是生成一个扩展名为.gch的巨大文件。

  2. 您获得的错误是链接时间。在创建.so文件时,您实际上并未链接代码。因此,假定所有未定义的符号都出现在某个地方。链接它时,链接器将找到这些符号。因此,您应该将所有.cpp文件编译/链接在一起。错误将消失。

  3. 此外,对于templates,代码的定义必须始终可见。因此,无论何时编写模板化函数/变量定义,都要在任何地方包含该文件。

    修改: 你可以使用模板类virtual方法;但你不能拥有virtual template methods

    template<typename T>
    class A {
      virtual void foo(int); // ok
    };
    
    class A {
      template<typename T>
      virtual void foo(T); // illegal
    };