3

以下に追加の質問、2011 年 4 月 11 日

C をサポートできるようにする必要がありますが、共有ライブラリ DLL/Sos とテスター プログラムのクロスプラットフォーム セットを C++ で開発しています。ライブラリはオブジェクト コードとしてのみ出荷されますが、テスター プログラムはソースと共に出荷されるので、私たちの顧客はサンプルコードを持つことができます。このため、実行時にロードされるライブラリ、つまり dlopen()/LoadLibraryA() を使用した動的リンクを設計しています。

Umbutu 10.04 で g++ 4.4.3-4 を使用し、Vista/64 (32 ビット モード) で VC++ 2008 を使用しています。

すべてが Windows で問題なく動作するようです (現在)。ただし、Linux でコンパイルすると、特定できないエラーが発生します。

テスターとライブラリには、複数の .cpp と .h でコード化された複数のクラスがあります。メイン エントリ ポイントを除くライブラリ内のクラスとほとんどすべては、名前空間 DISCOVER_NS にあります。

プロジェクトの簡単なスケッチを次に示します。

最初に、認めます。コードが読みやすくなるように、名前の束を短くしました。

発見.cpp

  • タイプ DiscoverObject の theMainObject と呼ばれるポインタを持つクラス オブジェクトを作成します。

  • MainObject を呼び出し元プログラムに void* として返す extern "C" 関数があります。

  • DiscoverObject にはいくつかのメソッドがあり、別の cpp と .h にある他のクラスをインスタンス化します。特定のメソッドの 1 つに Hello() という名前が付けられており、これは期待どおりの動作を行い、"hello" テスト メッセージを出力します。


tester.cpp

  • ライブラリへのハンドルを取得します

  • MainObject を返す関数への関数ポインタを取得します。

  • 関数 (ポインター) を実行し、返されたアドレスを void* から DISCOVER_NS::DiscoverObject* aDiscoverObject にキャストします。

  • aDiscoverObject->Hello() を実行します。


私はコンパイルします:

CC = @g++

gflags = -g3

cflags = -fPIC -Wall -pedantic

lib_linkflags := -shared -fPIC -lstdc++ -lrt -lpthread -rdynamic

tester_linkflags := -ldl -lpthread

定義 = -D_ linux _ -D_DEBUG -D_IPC_ARCH_INTEL=1 -D_THREAD_SAFE


コンパイルすると、次のエラーが表示されます: *Tester.cpp:142: undefined reference to `Discover_NS::DiscoverObject::hello()'*

また、discover.so から他にも未定義の参照エラーがたくさん出ます。たとえば、次のようになります。


SO extern "C"で事実上すべてを作成しようとしました。変わりはない。

次のようなステートメントをdiscover.cppに入れてみました: extern void Discover_NS::OtherClass::method( args ); しかし、それは「クラス外の宣言は定義ではありません」というエラーについてのエラーを私に与えます。


コードを見るのに役立つことはわかっていますが、投稿するために何か小さなものを作り上げる時間が必要です。

この混乱を解決するためのアイデアを提供できる人はいますか?

ありがとう、

ウェス

Dmitry の解決策はすべての修正ではありませんでしたが、解決策に必要な要素でした。メイクファイルを調べたところ、意図せずに重複した行がいくつか見つかりましたが、それらは削除しました。また、コンパイル手順にコード化された -o のパスが間違っていた 2 つの「タイプミス」が見つかりました。壊れた手順で logger.cpp と RemException.cpp がコンパイルされました。

./common/logger.o : ./common/logger.cpp
    $(CC) $(gflags)  $(cflags) -c  $(defines)  -I ./common  
        -I ./EdgeIO  -I ./Discover   
        -o ./common/Debug/logger.o   <+++++++++ path to .o was wrong
        ./common/logger.cpp   2>&1  | tee ./RemKonTester/logger.ERR

その後、本当のバグを見つけました。Discover ディレクトリにあるすべての .cpp をコンパイルしていないという事実を完全に見逃していました。すべての nit-pics を削除するのにかなりの時間がかかりましたが、今ではメイクファイルから問題なくコンパイルできます。

元の質問の新しいバージョン: makefile を介して動作することがわかったので、makefile が行っているのと同じことを行うように Eclipse に指示するにはどうすればよいですか?

ありがとうドミトリー。

ウェス

さて、私の問題はまだここにあります。

Dmitry (@Dmitry) の提案を使用してコードをコンパイルしています。ただ、それらは別の問題を引き起こしているようです。実行時に、ライブラリをメインのテスト プログラムに動的にリンクさせたいと考えています。-l Discover -l EdgeIOをリンクに追加すると、すべてがコンパイルされますが、静的リンクが得られます。

参考までに、未使用の「pi」は、SOに浮動小数点数が含まれているため、浮動小数点サポートでコンパイルされます。呼び出し元が浮動小数点数を使用したい場合に必要です。浮動小数点を含めてg ++をcomkpileに強制するより良い方法はありますか?

Dmitry が見つけてくれた多くのバグを修正した後、次の出力が得られます。

make
./Discover/dllmain.cpp: In function ‘void InitalizeLibraryServices()’:
./Discover/dllmain.cpp:175: warning: unused variable ‘pi’


./EdgeIO/dllMain.cpp: In function ‘void InitalizeLibraryServices()’:
./EdgeIO/dllMain.cpp:158: warning: unused variable ‘pi’


linking RemKonTester
    gflags = -g3
    tstlinkflags = -ldl  -lpthread 
    defines =  -D__linux__   -D_DEBUG   -D_IPC_ARCH_INTEL=1   -D_THREAD_SAFE

./RemKonTester/Debug/RemKonTester.o: In function `main':
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:81: undefined 
    reference to `RemKon_EdgeIO::EdgeIoObject::hello()'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:111: undefined 
    reference to `RemKon_Discover::DiscoverObject::hello()'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:116: undefined 
    reference to `RemKon_Discover::DiscoverObject::SetLogLevel(unsigned int)'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:117: undefined 
    reference to `RemKon_Discover::DiscoverObject::hello()'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:118: undefined 
    reference to `RemKon_Discover::DiscoverObject::LocalIpAddress(int)'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:122: undefined 
    reference to `RemKon_Discover::DiscoverObject::RegisterCallback(bool(*)
    (void*), void*)'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:123: undefined 
    reference to `RemKon_Discover::DiscoverObject::Search()'

collect2: ld returned 1 exit status

Eclipse から同じ一連のエラー メッセージが表示されます。

RemKonTester.cpp には、これらの項目が宣言されているすべての .h が含まれています。私は宣言extern "C"でそれらを試しましたが、そうではありませんでした。

助けを期待して、

ウェス

4

2 に答える 2

5

あなたの問題は次の位置にあるようです-l<library>

$(CC)  $(gflags)  $(tstlinkflags) $(defines)      -L ./Debug    -ldiscover   
        -ledgeio -o ./Debug/RemKonTester  ./RemKonTester/Debug/RemKonTester.o  
        ./RemKonTester/Debug/logger.o  ./RemKonTester/Debug/libraryClass.o   
        2>&1  | tee ./RemKonTester/make.ERR

それらはオブジェクトファイルの後にある必要があります。これは、コマンドラインでそれらが検出されたときにリンカーがそれらをロードし、未定義のシンボルを検索するためです。

詳細についてはman ld、(特に-lオプション)を参照してください。

-l namespec

..。

リンカは、コマンドラインで指定された場所でアーカイブを1回だけ検索します。アーカイブが、コマンドラインでアーカイブの前に表示されたオブジェクトで未定義のシンボルを定義している場合、リンカはアーカイブからの適切なファイルを含めます。ただし、コマンドラインの後半に表示されるオブジェクト内の未定義のシンボルによって、リンカがアーカイブを再度検索することはありません。

これはあなたのために働くはずです:

$(CC)$(gflags)$(tstlinkflags)$(defines)-L ./Debug -o ./Debug/RemKonTester ./RemKonTester/Debug/RemKonTester.o ./RemKonTester/Debug/logger.o ./RemKonTester/ Debug / libraryClass.o -ldiscover -ledgeio 2>&1 | tee ./RemKonTester/make.ERR

PS StackOverflowで質問を編集するオプションがあることに注意してください。回答として追加情報を投稿することは、良い習慣ではありません。

于 2011-04-06T19:03:58.763 に答える
0

EDITED:ついに「エディタ」を見つけました。より美しくしました。wjm

遅れて申し訳ありません。昨夜、倒れた木を前庭から取り出さなければなりませんでした。

注: 元のメモの名前をいくつか変更して、短くしています。この答えにはすべてが綴られています。


g++ 出力...

$ make
./EdgeIO/dllMain.cpp: In function ‘void InitalizeLibraryServices()’:
./EdgeIO/dllMain.cpp:158: warning: unused variable ‘pi’
./Discover/dllmain.cpp: In function ‘void InitalizeLibraryServices()’:
./Discover/dllmain.cpp:174: warning: unused variable ‘pi’
./RemKonTester/RemKonTester.cpp: In function ‘int main(int, char**)’:
./RemKonTester/RemKonTester.cpp:130: warning: ISO C++ forbids casting between     
pointer-to-function and pointer-to-object
./RemKonTester/RemKonTester.cpp:152: warning: unused variable ‘searchResp’
./RemKonTester/libraryClass.cpp: In member function ‘int 
library::AttachLibrary()’:
./RemKonTester/libraryClass.cpp:132: warning: ISO C++ forbids casting between 
pointer-to-function and pointer-to-object
./RemKonTester/libraryClass.cpp:154: warning: ISO C++ forbids casting between 
pointer-to-function and pointer-to-object
./RemKonTester/Debug/RemKonTester.o: In function `main': 
/home/wmiller/Projects/Eclipse/
./RemKonTester/RemKonTester.cpp:142: undefined reference to 
`RemKon_Discover::DiscoverObject::hello()'
collect2: ld returned 1 exit status
gflags = -g3
tstlinkflags = -ldl  -lpthread
defines =  -D__linux__   -D_DEBUG   -D_IPC_ARCH_INTEL=1   -D_THREAD_SAFE
./Debug/libdiscover.so: undefined reference to     
`RemKon_Discover::RemKonDeviceList::~RemKonDeviceList()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::ClientPort(unsigned short)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::PayloadSize(unsigned int)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::Socket() const'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemKonDeviceList::Count() const'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemException::~RemException()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::UDPbinder()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::ListenTimeOut(int)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::ServerPort(unsigned short)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemKonDeviceList::Next()'
./Debug/libdiscover.so: undefined reference to `RemKon_Discover::Log(char 
const*, ...)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::UDPlisten(unsigned char*, int*, sockaddr_in*, int*)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemException::RemException()'
./Debug/libdiscover.so: undefined reference to `RemKon_Discover::VerboseLogging()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::RegisterCallbackFunction(void (*)(void*, unsigned 
char*, int), void*)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemKonDeviceList::First()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::TestData(unsigned int, unsigned int, unsigned char*, 
unsigned int)'
./Debug/libdiscover.so: undefined reference to `RemKon_Discover::Logging()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::MessageLength(int)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::LocalIpAddress(int)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::UDPsend()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::DiscoverObject::LocalIpAddress() const'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::SetBroadcastMode()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::MakeMacAddressString(unsigned char*, char*)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemKonDeviceList::RemKonDeviceList()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemKonDeviceList::New()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::ActivateLogging(unsigned int)'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::RemSocket()'
./Debug/libdiscover.so: undefined reference to 
`RemKon_Discover::RemSocket::Payload(unsigned int)'
collect2: ld returned 1 exit status

そして、これがメイクファイルです。申し訳ありませんが、私は make をあまり話せません。そのため、makefile は機能的であり、きれいではありません。

CC = @g++
gflags = -g3
cflags = -fPIC -Wall -pedantic
liblinkflags := -shared -fPIC -lstdc++ -lrt -lpthread -rdynamic
tstlinkflags := -ldl  -lpthread
defines = -D__linux__   -D_DEBUG   -D_IPC_ARCH_INTEL=1   -D_THREAD_SAFE


all : clean edgeio discover tester


############################################

edgeio : ./EdgeIO/dllMain.o ./EdgeIO/EdgeIO.o
$(CC) $(gflags)  $(liblinkflags) $(defines)    -Wl,-soname,./Debug
    /libedgeio.so.1  -o ./Debug/libedgeio.so.1.0 ./EdgeIO/Debug/edgeio.o  
    ./EdgeIO/Debug/dllmain.o    2>&1  | tee ./EdgeIO/make.ERR
            @cd ./Debug; ln -sf libedgeio.so.1.0    libedgeio.so
        @cd ./Debug; ln -sf libedgeio.so.1.0    libedgeio.so.1

./EdgeIO/dllMain.o : ./EdgeIO/dllMain.cpp
        $(CC) $(gflags)  $(cflags) -c $(defines)   -I ./common  -I ./EdgeIO  
    -I ./Discover   -o./EdgeIO/Debug/dllmain.o  ./EdgeIO/dllMain.cpp   2>&1  
    | tee ./EdgeIO/dllmain.ERR

./EdgeIO/EdgeIO.o : ./EdgeIO/EdgeIO.cpp
    $(CC) $(gflags)  $(cflags) -c $(defines)   -I ./common  -I ./EdgeIO  
    -I ./Discover   -o./EdgeIO/Debug/edgeio.o  ./EdgeIO/EdgeIO.cpp     2>&1  | 
    tee ./EdgeIO/EdgeIO.ERR

############################################

discover : ./Discover/Discover.o ./Discover/dllmain.o
    $(CC) $(gflags)  $(liblinkflags) $(defines)    -Wl,-soname,./Debug
        /libdiscover.so.1  -o ./Debug/libdiscover.so.1.0          ./Discover/Debug
        /Discover.o  ./Discover/Debug/dllmain.o    2>&1  | tee ./Discover/make.ERR
    @cd ./Debug; ln -sf libdiscover.so.1.0  libdiscover.so
    @cd ./Debug; ln -sf libdiscover.so.1.0  libdiscover.so.1

./Discover/Discover.o : ./Discover/Discover.cpp
    $(CC) $(gflags)  $(cflags) -c $(defines)   -I ./common  -I ./EdgeIO  
    -I ./Discover   -o./Discover/Debug/Discover.o  ./Discover/Discover.cpp  
     2>&1  | tee ./Discover/Discover.ERR

./Discover/dllmain.o : ./Discover/dllmain.cpp
        $(CC) $(gflags)  $(cflags) -c  $(defines)  -I ./common  -I ./EdgeIO  
        -I ./Discover   -o./Discover/Debug/dllmain.o  ./Discover/dllmain.cpp   
        2>&1  | tee ./Discover/dllmain.ERR

############################################

tester : ./RemKonTester/RemKonTester.o ./common/logger.o  ./RemKonTester
        /libraryClass.o    ./common/RemException.o
    $(CC)  $(gflags)  $(tstlinkflags) $(defines)       
        -L ./Debug -o ./Debug/RemKonTester  ./RemKonTester/Debug
        /RemKonTester.o  ./RemKonTester/Debug/logger.o  ./RemKonTester/Debug
        /libraryClass.o   2>&1  | tee ./RemKonTester/make.ERR

    @echo "gflags = $(gflags)"   2>&1  | tee ./RemKonTester/make.ERR
    @echo "tstlinkflags = $(tstlinkflags)"   2>&1  | tee ./RemKonTester/make.ERR
    @echo "defines =  $(defines)"   2>&1  | tee ./RemKonTester/make.ERR

    $(CC)  $(gflags)  $(tstlinkflags) $(defines)      -L ./Debug    -ldiscover   
        -ledgeio -o ./Debug/RemKonTester  ./RemKonTester/Debug/RemKonTester.o  
        ./RemKonTester/Debug/logger.o  ./RemKonTester/Debug/libraryClass.o   
        2>&1  | tee ./RemKonTester/make.ERR

./RemKonTester/RemKonTester.o : ./RemKonTester/RemKonTester.cpp
    $(CC) $(gflags)  $(cflags) -c $(defines)   -I ./common  -I ./EdgeIO  
        -I ./Discover   -o ./RemKonTester/Debug/RemKonTester.o   ./RemKonTester
        /RemKonTester.cpp   2>&1  | tee ./RemKonTester/RemKonTester.ERR

./common/logger.o : ./common/logger.cpp
    $(CC) $(gflags)  $(cflags) -c  $(defines)  -I ./common  -I ./EdgeIO  
        -I ./Discover    -o ./RemKonTester/Debug/logger.o  ./common/logger.cpp
        2>&1  | tee ./RemKonTester/logger.ERR

./RemKonTester/libraryClass.o : ./RemKonTester/libraryClass.cpp
    $(CC) $(gflags)  $(cflags) -c  $(defines)  -I ./common  -I ./EdgeIO  
        -I ./Discover    -o ./RemKonTester/Debug/libraryClass.o 
        ./RemKonTester/libraryClass.cpp   2>&1  | tee ./RemKonTester
        /libraryClass.ERR

./common/RemException.o : ./common/RemException.cpp
    $(CC) $(gflags)  $(cflags) -c  $(defines)  -I ./common  -I ./EdgeIO  
        -I ./Discover    -o ./RemKonTester/Debug/RemException.o ./common
        /RemException.cpp   2>&1  | tee ./RemKonTester/RemException.ERR


############################################

clean :
    @rm -f *.ERR
    @rm -f ./common/*.ERR
    @rm -f ./EdgeIO/*.ERR
    @rm -f ./Discover/*.ERR
    @rm -f ./RemKonTester/*.ERR

    @rm -f QEMACRO*
    @rm -f ./common/EdgeIO/QEMACRO*
    @rm -f ./EdgeIO/QEMACRO*
    @rm -f ./Discover/QEMACRO*
    @rm -f ./RemKonTester/QEMACRO*

    @rm -f ./Debug/*.o
    @rm -f ./common/Debug/*.o
    @rm -f ./EdgeIO/Debug/*.o
    @rm -f ./Discover/Debug/*.o
    @rm -f ./RemKonTester/Debug/*.o

    @rm -f ./Debug/*.log
    @rm -f ./common/Debug/*.log
    @rm -f ./EdgeIO/Debug/*.log
    @rm -f ./Discover/Debug/*.log
    @rm -f ./RemKonTester/Debug/*.log

    @rm -f ./Debug/*.so*

############################################

ありがとう、

ウェス

于 2011-04-06T14:33:52.683 に答える