0

編集:回答に応じて、行った変更で質問を更新しました。 私が書いた小さなライブラリにリンクしようとしていますが、これはC ++で行われていることを学ぶために書いたものです。G++ は と不平を言っていundefined referenceます。

リンクしたいライブラリのルートディレクトリは directory にあり~/code/gklib/cxx/ます。このディレクトリの構造は次のとおりです。

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

flagを使用してコンパイルgk.cc-c、結果のオブジェクト ファイルを.aファイルに変換しましたar rvsc lib/libgk.a libgk.o

このライブラリのクライアントは folder にあります~/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)

コマンドで多くのバリエーションを試しましたが、結果はありませんでした。インターネットには、私にとってはうまくいかなかった指示が記載されたチュートリアルやフォーラムがたくさんあります。このコードは、すべてが 1 つのファイルにあるときに完全に実行されました。この問題を解決するにはどうすればよいですか? 前もって感謝します。

4

3 に答える 3

1

私はそれがもっと似ていると思います:

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

-lgklib、not -Igklib(-Iオプションでインクルード フォルダーを指定)

gklib.aただし、 byの名前を変更する必要がありますlibgklib.a

たぶん-B../gklib/cxx/lib、削除することもできます。試してみてください:)

于 2013-02-07T16:20:27.477 に答える
0

私はこれこの質問の助けを借りて、この問題を解決しました。問題は、それがテンプレート関数であるという事実にvoid insertionSort(T *)あり、テンプレート関数はヘッダーファイルにのみ実装できます。この理由は、コンパイラがの定義に到達して、テンプレートへの引数として異なるタイプを使用して、コンパイラへの呼び出しごとに新しい関数を作成する必要があるためです。この関数の定義をに移動しましたgk.h。これにより、コンパイルとリンクが成功しました。

于 2013-02-07T17:51:50.150 に答える
0

いくつかの問題があります: 順番に:

  • これが正確なコマンドラインである場合、-Lオプションは上に示した構造を指していません ( cxxパスに no がない場合)。

  • を使用している理由がわかりません-Bこれは、ライブラリなどを探す場所をコンパイラに伝えます。通常、これは、変更したコンパイラの一部をテストする場合にのみ必要です。

  • ライブラリに対してリンクするように指定した場所がわかりません。ライブラリは通常の命名規則 ( ) を尊重しないため、(オブジェクト ファイルを指定するのと同じ方法で) 直接指定する必要があり、オプションは使用されません。あるいは、 などの名前を付けて、オブジェクト ファイルのにコマンド ラインにa を追加します。libname.a-Llibgk.a-lgk

  • 最後に、エラー メッセージはテンプレートのインスタンス化に言及しています。これは通常、テンプレートの実装がヘッダーではなくソース ファイルにあるために発生します。標準では、テンプレートのインスタンス化をトリガーするときに、実装が可視であることを要求しています。g++ (および他のほぼすべてのコンパイラ) の動作方法は、実装が表示されない場合、テンプレートが別の翻訳単位でインスタンス化されると想定し、それへの外部参照を出力することです。ただし、実装がソースにある場合、インスタンス化は行われず、リンカー エラーが発生します。(テンプレートがインスタンス化されていないため、インスタンス化用のアセンブラーもどこにもありません。) ヘッダーの最後にソース コードを含め、個別にコンパイルしないでください。

于 2013-02-07T16:19:24.433 に答える