2011-12-16 3 views
2

私はLinux上ですが、問題はC++クラスの共有オブジェクトに関するものです。.soがメインの実行可能ファイルからクラスを使用しようとすると、dlopen()は未解決のシンボルエラーを返します。どうして?

共有オブジェクトがメインの実行可能ファイルにリンクされたリソースを使用しようとすると、問題が発生します。私は、次のコードを持っている:

loader.cpp:

#include <dlfcn.h> 
#include <iostream> 
#include "CommonInfo.h" 

using namespace std; 

int main(int argc, char** argv) { 
    for(int i=1; i<argc; ++i) { 
     string pth = "./"; 
     pth.append(argv[i]); 
     void* dh = dlopen(pth.c_str(), RTLD_NOW); 
     if(dh==NULL) { 
      cerr << dlerror() << endl; 
      return 1; 
     } 

     CommonInfo::GetInfoFunc getInfo = (CommonInfo::GetInfoFunc)(dlsym(dh,"getInfo")); 
     if(getInfo==NULL) { 
      cerr << dlerror() << endl; 
      return 1; 
     } 

     CommonInfo* info = getInfo(); 
     cout << "INFO: " << info->getX() << endl; 
     delete info; 
    } 
    return 0; 
} 

CommonInfo.h:

#include <string> 

class CommonInfo { 
    public: 
     typedef CommonInfo* (*GetInfoFunc)(); 
    private: 
     std::string x; 
    public: 
     CommonInfo(const std::string& nx); 
     std::string getX() const; 
}; 

EDIT: 私はaccidentaly CTRL-Cに+ CTRL-V CommonInfoのソースを忘れてしまいました.cppはここに。もちろん、それはCommonInfo.cppので、コンパイル時があります:

#include "CommonInfo.h" 

CommonInfo::CommonInfo(const std::string& nx) : x(nx) { 
} 

std::string CommonInfo::getX() const { 
    return x; 
} 

A Plugin.hヘッダー:

#include "CommonInfo.h" 
extern "C" CommonInfo* getInfo(); 

非常にシンプルPlugin.cpp:

#include <iostream> 
#include "Plugin.h" 
#include "CommonInfo.h" 

using namespace std; 

CommonInfo* getInfo() { 
    return new CommonInfo("I'm a cat!"); 
} 

コンパイルがあります行われる:

g++ -rdynamic -ldl -Werror CommonInfo.cpp loader.cpp -o loader 
g++ -shared -fPIC -Werror Plugin.cpp -o Plugin.so 

Runn

./loader Plugin.so 

をし、エラーがそこに行く:INGの

./loader: symbol lookup error: ./Plugin.so: undefined symbol: _ZN10CommonInfoC1ERKSs 

を確かに、nm Plugin.so | grep -i CommonInfoとPlugin.so内を調べて、それは完全にOKです(未解決)このシンボルのための 'U' を与えます。 また、nm loader.so | grep -i CommonInfoのローダーのバイナリを見ると、「T」のシンボルも見つかるはずです。これもOKです。 質問:メインのバイナリから問題のシンボルをdlfcn.hで解読しないでください。この機能がなければ、これらのものを使用するのは非常に難しくなります... CommonInfoのクラスファクトリ関数を記述し、プラグインからdlfcnをロードして呼び出す必要がありますか?事前に

おかげで、 デニス

+0

(訂正:C++クラスの共有オブジェクトではありませんが、この投稿を書き始めるとPlugin.soにクラスがありましたが、エラーをより明確にするためにそれを取り除きました。) – dennis90

+0

CommonInfoのコンストラクタに関連する問題です。それはどこに定義されていますか? – Emiliano

+0

おっと、そうです、私はここにそれを書くのを忘れました。:) – dennis90

答えて

5

私はあなたのコードをよく見ていないが、私は-Eで実行可能ファイルをリンクしていないときは、タイトルに説明のように、私は過去に行動を発見しました。 (またはldではなくgccとリンクする場合は-Wl,-E

すべてのプラットフォームで共有ライブラリが呼び出し元のバイナリからシンボルを受け取るとは限りません。 Linuxと* BSDを使えます。しかし、Windowsに移植する場合は、このパターンを使用することはできません。私はあなたにこれをさせないUnixタイプのOSもあると信じています。

+0

まあ、ありがとうございますが、それを解決していないようです: 私は 'g ++ -ldl -W、-E -o loader CommonInfo.o loader.o'とリンクします。 すべてが正しいとすれば、 'nm -D loader'は私に問題のシンボルを表示すると思います...しかし残念ながら、-Eオプションを指定してもそれはできません。 :/ /私はリンク時に何か間違っているのでしょうか? – dennis90

+0

IT制作!あなたの解決策は正しいです、私はちょうど-lの代わりに-W、-Eを偶然書きました。 Lol、単純な手紙の時間の無駄な部分は... :) – dennis90

+0

@asveikau:Windows上のEXEからシンボルをエクスポートすることができます。しかし、Windowsには2レベルのシンボル名前空間があるので、プラグインはメインEXEのシンボルを明示的に要求する必要があります(メインEXEのインポートライブラリにリンクするか、 'GetProcAddress()'を呼び出す)。 – bk1e

関連する問題