2

以下のmakefileを使用してプログラム実行可能ファイルを作成しているときに、静的ライブラリをリンクしようとしています。

IDIR =../inc
CC=g++ -g
CFLAGS=-I$(IDIR)
WFLAGS=-Wall -W
OFLAGS=-O3
DLINUX=-D_LINUX

ODIR=obj
LDIR =../lib
LIBS=-lm

_OBJ = testclient.o 
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))

$(ODIR)/testclient.o: testclient.c
    $(CC) -c $< $(CFLAGS) -o $@
$(ODIR)/file2.o: file2.c
    $(CC) -c $< $(CFLAGS) -o $@

testclient: $(OBJ)
    $(CC) -o $@ $^ $(LIBS) -lccn -pthread 

.PHONY: clean

clean:
    rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~ 

-lccn' 'パラメーターの順序の変更から、関数がライブラリーに存在するかどうかのチェック(nm libccn.a必要な関数をライブラリーに与える)まで、利用可能なすべてを試しましccn_create()た。返されるエラーは次のとおりです。

obj/testclient.o: In function `main':
/root/testClient/src/testclient.c:91: undefined reference to `ccn_create()'

ライブラリlibccn.aはにあり/usr/local/libます。また、ディレクトリパスを変更し、-Lフラグを使用してその場所を検索してみました。どちらも動作しません。:( ..どうすればそれを機能させることができるかについてのアイデアはありますか?

4

1 に答える 1

4

私の推測では、それlibccn.aは C ライブラリであり、使用するヘッダーは C++ コンパイラによってインポートされるように設計されていません (extern "C" { }関数定義を囲むブロックはありません)。

C++ は、関数名をマングリングすることによる関数のオーバーロードをサポートしています。関数をブロックに入れるとextern "C" { }、C++ は名前マングリングを無効にします (したがって、オーバーロードを無効にします)。ここで、エラー メッセージに記載されている関数は ですccn_create()。に注意してください()。これは、関数の型がわかっていることを意味し、したがって、検索された名前はマングルされた名前でした。

あなたがそうするとき、あなたnm libccn.aは本当の名前を見て、それはccn_createです. それはマングルされた名前ではありません。これを修正するには、関数定義をexport "C" { }ブロックで囲む必要があります。#includeこれを行う最も簡単な方法は、をそのようなブロックで囲むことです。

ところで、これを行うことでエラーを再現できます。

$ echo 'void ccn_create();' > ccn.h
$ echo '#include "ccn.h"
void ccn_create() { }' > ccn.c
$ echo '#include "ccn.h"
int main () {
  ccn_create();
  return 0;
}' > main.cc
$ gcc -o ccn.o -c ccn.c
$ g++ -o main main.cc ccn.o
Undefined symbols for architecture x86_64:
  "ccn_create()", referenced from:
      _main in cc8XnYRq.o
ld: symbol(s) not found for architecture x86_64
$ echo 'extern "C" {
#include "ccn.h"
}
int main () {
  ccn_create();
  return 0;
}' > main.cc
$ g++ -o main main.cc ccn.o
于 2013-02-04T10:09:42.923 に答える