0

编辑:根据答案,我已经用我所做的更改更新了我的问题。 我正在尝试链接到我编写的一个小库,以了解这是用 C++ 完成的,但没有运气。G++ 抱怨undefined reference.

我要链接的库的根目录在 directory 中~/code/gklib/cxx/。该目录的结构如下:

~/code/gklib/cxx/
|
|`-> gk.{hh,cc}
|`-> libgk.o
|
 `-> lib/
     |
     `-> libgk.a

我已经gk.cc使用-c标志编译,然后将生成的目标文件转换为带有.a 的.a文件ar rvsc lib/libgk.a libgk.o

该库的客户端位于文件夹~/code/cpp。在此目录中,我再次编译some_stuff.cc为目标文件,然后尝试使用以下命令链接到它:

$ cxx some_stuff.o -L../gklib/cxx/lib -lgk -o some_stuff

我收到此错误:

some_stuff.o: In function `main':
some_stuff.cc:(.text+0x49): undefined reference to `void GK::algorithms::insertionSort<int, 5ul>(int*)'
collect2: error: ld returned 1 exit status

这些是这些文件的内容:

~/code/cpp/some_stuff.cc

#include <cstdlib>
#include <iostream>
#include <gk.hh>

using namespace std;

int main(int argc, char **argv) {
  int i = -1;
  int arr[5] = { 3, 4, 2, 1, 5 };
  const size_t len = sizeof(arr)/sizeof(int);
  GK::algorithms::insertionSort<int, len>(arr);
  while(++i < 5)
    cout << arr[i] << " ";
  cout << endl;
  exit(EXIT_SUCCESS);
}

~/code/gklib/cxx/gk.cc

#include "gk.hh"
template<class T, size_t len>
void GK::algorithms::insertionSort(T arr[len]){
  // insertion sort
}

~/code/gklib/cxx/gk.hh

#pragma once
#include <cstdlib>

#define NAMESPACE(ns) namespace ns {
#define END_NAMESPACE(ns) }

NAMESPACE(GK)
NAMESPACE(algorithms)

template<class T, size_t len>
extern void insertionSort(T arr[len]);

END_NAMESPACE(algorithms)
END_NAMESPACE(GK)

我对我的命令尝试了很多变体,但没有结果。互联网上到处都是教程和论坛,其中包含对我不起作用的说明。当所有的东西都在一个文件中时,这段代码运行得很好。我该如何解决这个问题?提前致谢。

4

3 回答 3

1

我认为它更像是:

cxx some_stuff.o -L$HOME/gklib/cxx/lib -B../gklib/cxx/lib -lgklib -o some_stuff

-lgklib,而不是-Igklib-I选项指定包含文件夹)

但你必须重命名你gklib.alibgklib.a

也许你甚至可以删除-B../gklib/cxx/lib,试试看:)

于 2013-02-07T16:20:27.477 回答
0

我看到几个问题:按顺序:

  • 如果这是您的确切命令行,则该-L选项不指向您上面显示的结构( cxx路径中没有)。

  • 我不知道你为什么使用-B. 这告诉编译器在哪里寻找它的库等。通常,只有当你想测试你修改的编译器的部分时才需要这样做。

  • 我没有看到您指定链接到库的位置。由于该库不遵守通常的命名约定 ( ),因此您必须直接指定它(以与指定目标文件相同的方式),并且不使用该选项。或者,您将其命名为 或类似名称,并在您的目标文件之后添加一个到命令行。libname.a-Llibgk.a-lgk

  • 最后,错误消息是指模板的实例化。这通常是因为模板的实现在源文件中,而不是在头文件中。该标准要求实现在触发模板的实例化时是可见的。g++(和几乎所有其他编译器)的工作方式是,如果实现不可见,他们假设模板将在另一个翻译单元中实例化,并输出对它的外部引用。但是,如果实现在源代码中,则不会有实例化,并且您将收到链接器错误。(你也不会在任何地方找到用于实例化的汇编程序,因为模板还没有被实例化。)你应该在标题的底部包含源代码,而不是单独编译它。

于 2013-02-07T16:19:24.433 回答
0

在这个这个问题的帮助下,我已经解决了这个问题。问题在于它void insertionSort(T *)是一个模板函数,而模板函数只能在头文件中实现。这样做的原因是,编译器需要达到 的定义,以便为每次调用它创建一个新函数,并使用不同的类型作为模板的参数。我已将此函数的定义移至gk.h,从而成功编译和链接。

于 2013-02-07T17:51:50.150 回答