0

C で書かれた中規模 (10,000 行程度) のプログラムを C++ プログラムに統合しています。C コードへのインターフェイスとして新しいクラスを作成したBWAGenomeので、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
}

2番目の編集:多くの魂の検索の後、問題は私が考えていたもののほとんどとはまったく無関係であることに気付きました. 詳細については、私の回答を参照してください。

4

7 に答える 7

2

と を探していることに気付きましBWAGenome::BWTRestoreBWTBWAGenome::GetMatches。これらは、ルート名前空間のグローバル フリー関数ではなく、探しているメンバー関数です。

BWTRestoreBWTC 関数への呼び出しを意味する呼び出しを::BWTRestoreBWTコード内での呼び出しに変更して、何が起こるかを確認してください。への呼び出しについても同じことを行いますGetMatches

そして、静的 C++ 関数から C 関数を呼び出す必要があると言った人は完全に間違っています。そうなると、標準ライブラリを C++ の静的関数でラップせざるを得なくなりますが、それはばかげています。

于 2009-12-12T07:08:37.893 に答える
2

nm プログラムを使用して、プログラムで定義および参照されているシンボルの出力を取得してみてください。

nm file.o | grep BWTRestoreBWT

シンボルは T または U で表示されます。T は名前が定義されていることを意味し、後者はシンボルが定義されていないが呼び出されていることを意味します。リンクするには、各 U に対応する T が必要です。

ヘッダー ファイルで定義されていない限り、関数にインライン修飾子がないことを確認してください。

于 2009-12-12T08:05:53.160 に答える
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()関数とは、ラップされている C 関数のGetMatches()一部ですか、それとも C 関数ですか? class BWAGenome後者の場合は、それらの関数のヘッダーを間違った場所に含めていることを示しています (実際には、おそらく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()inの宣言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(より正式には「名前空間スコープ」として知られています)。

これで、現在のリンカー エラーが修正されるはずです。似たような名前の何かが見つからないというエラーが発生した場合は、C 関数に対しても同様bwt_restore_bwtに行う必要があることがわかります 。extern "C"

于 2009-12-12T08:07:13.000 に答える
1

BWAGenome::BWTRestoreBWT関数を含むライブラリ/オブジェクトの場所をリンカーに伝えましたか? すべてを個別にコンパイルするため、出力 .o ファイルを明示的にリンクする必要があります。

このリンク エラーを引き起こす可能性のある 2 つの理由は、次のとおりです。

  1. 検索された名前の定義がありますが、リンカーにそれを与えていません
  2. リンカーに指定したオブジェクト ファイルにメソッドが含まれていない - つまり、実装していない (または実装したと思っていたが、実装に「間違った」名前を付けた)。
于 2009-12-12T08:17:20.877 に答える
1

非クラス メンバー関数で static キーワードを使用すると、その関数はローカル リンケージを持ちます。つまり、コンパイル ユニット、つまり .cpp ファイルの外側では表示されません。static キーワードを取得するか、関数本体をインクルード ファイルに入れる必要があります。

クラスメンバー関数のコンテキストでは、静的には異なる意味があります。この場合、 static を使用すると、クラス オブジェクトをインスタンス化せずに関数を呼び出すことができます。

于 2009-12-13T00:22:24.887 に答える
0

本当に同じ形の関数が宣言されているか確認しましたか?

を探していBWAGenome::BWTRestoreBWT(char const*)ますが、代わりにBWAGenome::BWTRestoreBWT(char *)( なしでconst) を宣言している可能性がありますか?

于 2009-12-12T06:49:12.397 に答える