2017-11-24 7 views
0

共有ライブラリを作成しました。ここではFooクラスを定義しました。 Fooクラスには、sayHi()という名前の関数があります。私の質問は、Fooオブジェクトfooを作成した後で、どうやってsayHi()を呼び出すことができるかです。私はここに自分のコードを入れます。ポインタを使用したC++呼び出しオブジェクトメソッド

mylib.h

#ifndef FUNTEST_MYLIB_H 
#define FUNTEST_MYLIB_H 


class Foo { 
public: 
    int id = 0; 
    void sayHi(); 
}; 


#endif //FUNTEST_MYLIB_H 

mylib.cpp

#include <iostream> 
#include "mylib.h" 

using namespace std; 

void Foo::sayHi() 
{ 
    cout << "Implemented by lib" << endl; 
    cout << "id is: " << id << endl; 
} 

Foo* create() 
{ 
    return new Foo(); 
} 

その後、私は、次のコマンドを使用しますが、共有ライブラリのコンパイル:クライアント側で

g++ -c -std=gnu++11 -fPIC mylib.cpp 
g++ -shared -fPIC -o mylib.so mylib.o 

を、私は2つを書きますファイル:

mylib2.cpp

#include <iostream> 
#include "mylib.h" 

using namespace std; 

void Foo::sayHi() { 
    cout << "Implemented by caller" << endl; 
    cout << "id is: " << id << endl; 
} 

main.cppに

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

using namespace std; 

Foo* (*create)(); 
void (*sayHi)(); 
int main() { 
    void* lib = dlopen("./mylib.so", RTLD_LAZY); 
    create = (Foo* (*)())dlsym(lib, "_Z6createv"); 
    sayHi = (void (*)())dlsym(lib, "_ZN3Foo5sayHiEv"); 

    Foo* foo = create(); 

    sayHi(); 
    foo->sayHi(); 

    foo->id = 100; 
    cout << "Set id to " << foo->id << endl; 

    /* 
    * 
    * how can I make the follow statement 'sayHi();' 
    * output the following content: 
    * Implemented by lib 
    * id is: 100 
    */ 
    sayHi(); // line 29, FIXME 
    foo->sayHi(); 

    return 0; 
} 

次のコマンドを使用してクライアントをコンパイルします。

./a.out:

g++ -std=gnu++11 main.cpp mylib.h mylib2.cpp -ldl 

は最終的にクライアントを実行出力は次のとおりです。

Implemented by lib 
id is: 0 
Implemented by caller 
id is: 0 
Set id to 100 
Implemented by lib 
id is: -1407102376 // FIXME 
Implemented by caller 
id is: 100 

「sayHi();」というステートメントを作成するにはどうすればよいですか?ライン29の出力以下の内容で:

Implemented by lib 
id is: 100 

私は私が直接sayHi()関数を呼び出す場合、fooのオブジェクトなしで、出力が間違っていることを知っています。しかし、どうすれば修正できますか?

答えて

0

main.cppのグローバル変数sayHiの宣言が間違っています。関数ポインタとして宣言しています。しかし、それはメンバ関数を指しているので、メンバ関数ポインタである必要があります。

void (Foo::*sayHi)(); 

あなたがそれを呼び出すときに、あなたがFooオブジェクト必要があります:あなたはsayHi方法virtualを作る場合

(foo->*sayHi)(); 

あるいは、あなたがするので、まったくのシンボルをロードする必要はありませんがvtableによって効果的に処理されます。

+0

あなたのお世話になって、すばやく返信いただきありがとうございます。もう1つの質問は、私はどのように関数のポインタを取得できますか?次のステートメントは間違っています: sayHi =(void(Foo :: *)())dlsym(lib、 "_ZN3Foo5sayHiEv"); – sunnycomes

+0

私はバーチャルにsayHi()を変更して、うまく動作します。しかし、もし私がそれをメンバポインタを使って参照したいのであれば?私はメソッドシンボルを得るためにdlsymを使うことを意味します。どうもありがとうございます。 – sunnycomes

+0

解決済み:reinterpret_cast (sayHi)= dlsym(lib、 "_ZN3Foo5sayHiEv"); – sunnycomes

関連する問題