0

私は今少し混乱しています。昨日、g ++で-rdynamicを使用しても、未定義のシンボルがありました。しかし、今はエラーがなく、それはさらに厄介です。

私の場合を少し説明するために、共有オブジェクトのようなプラグインを実行したいと思います。どちらが最善の方法かはまだ決めていません。

A)私の共有オブジェクトにはすべて、パラメーターを使用して呼び出されるレジスターと呼ばれる関数があります。これはプラグインマネージャーになります。

B)共有オブジェクトはクラスを定義し、ロード時にそのクラスのインスタンスを作成します。そのクラスのコンストラクターでは、アプリから静的シングルトンを取得し、自分で自動登録しようとします。

私が知る限り、私の最初の試みは今のところそれほど素晴らしいものではありませんでした。

main.cpp

#include "main.hpp"
#include <iostream>
#include <cstdio>
#include <dlfcn.h>

int S::shared = 0;

int main(int argc, char** argv){
    std::cout << "In main -> " << S::shared << "\n";

    void* triangle = dlopen("./libtwo.so", RTLD_LAZY);

    if(triangle == NULL){
        std::cout << "Error while loading so file\n" << dlerror() << "\n";
    }

    std::cout << "In main -> " << S::shared << "\n" << triangle;
    return 0;
}

main.hpp

class S {
    public:
    static int shared;

    S(){
        S::shared = 0;
    };
};

two.cpp

#include "main.hpp"
#include <iostream>

class MyObject {
    public:
    MyObject(){
        std::cout << "In two -> " << S::shared  << "\n";
    }
};

MyObject t();

そのサンプルでは、​​S::sharedが共有する静的オブジェクトです。この簡単なテストでは、intのみを使用しますが、将来的にはクラスのインスタンスになります。

ケースA)での私の唯一の試みは、セグメンテーション違反でした...私は本当に何を逃したのかわかりません。

//これまでの結果(今日)

piplup@vika:~/dev/WebDesign/Scproci$ scons -Q
g++ -o two.os -c -fPIC two.cpp
g++ -o libtwo.so -shared two.os
g++ -o main.o -c -fPIC main.cpp
g++ -o main -Wl,--export-dynamic main.o -ldl
piplup@vika:~/dev/WebDesign/Scproci$ ./main
In main -> 0
In main -> 0
4

2 に答える 2

1
#include "main.hpp" 
#include <iostream>  

class MyObject {     
    public:     
        MyObject(){         
            std::cout << "In two -> " << S::shared  << "\n";     
        } 
};  

MyObject* t;

__attribute__((constructor))
void init_two()
{
    t = new MyObject();
}

__attribute__((destructor))
void uninit_two()
{
    delete t;
}

これにより、期待どおりの結果が得られるはずです。ポインタは、通常の初期化が自動的に行われないため、共有オブジェクトで明示的に処理する方が簡単なため、使用されます。ポインタを使用したくない場合は、クラスに明示的な初期化を提供し、共有ライブラリの初期化関数で呼び出します。

* 編集 *

追加の実験を行いましたが、デフォルトのコンストラクターを使用している場合は暗黙的に使用し、デフォルト以外のコンストラクターを使用している場合は通常どおりに呼び出されるようです。

だからあなたはあなたを変えることができます:

MyObject t();

へ電話する:

MyObject t;

また、明示的な初期化関数が定義されていなくても機能します。

また

class MyObject {
public:
   MyObject() { /* as before */ };
   MyObject(int val)
   {
        S::shared = val;
        std::cout << "In two -> " << S::shared << "\n";
   }
};

MyObject t(10);

MyObject t();かどうかについて、コンパイラが混乱しているようです。は変数宣言、またはグローバルスコープでの関数宣言であり、関数宣言として扱います。

于 2011-08-22T19:17:46.947 に答える
0

すぐに私に飛びつく問題は、リンクユニットを分離する必要があるということです。静的クラスメンバーは、そのクラスの名前空間にラップされたグローバルです。

ここで、メインプログラムと共有オブジェクトのように2つのリンクユニットがある場合、両方がグローバルを持つ可能性が高く、fooそれらは別個の値になります。

また、two.cppのtの静的初期化が共有オブジェクトで実行されない理由は明らかではありません。おそらく、共有オブジェクトのある種のmain関数の前に発生することが保証されていません。

于 2011-08-22T18:39:58.547 に答える