2

これは私のプログラムのプラグイン機能についてです。インターフェイスを介してメインモジュールで使用できるプラグインにC++クラス(およびオブジェクト)が必要です。このようなインターフェースの継承:

typedef struct _rwd_plugin_root_t RWD_PLUGIN_ROOT_T;

struct RWD_PLUGIN_API _rwd_plugin_root_t
{
    virtual int add_ref() = 0;
    virtual int release() = 0;
}; 

typedef struct _rwd_plugin_base_t RWD_PLUGIN_BASE_T;

struct RWD_PLUGIN_API _rwd_plugin_base_t : _rwd_plugin_root_t
{
    virtual RWD_PLUGIN_TYPE_T get_plugin_type() = 0;
    virtual const char * get_plugin_label_a() = 0;
    virtual const wchar_t * get_plugin_label_w() = 0;
};

typedef struct _rwd_autocomplete_plugin_base_t RWD_AUTOCOMPLETE_PLUGIN_BASE_T;

struct RWD_PLUGIN_API _rwd_autocomplete_plugin_base_t : _rwd_plugin_base_t
{
    virtual int set_proxy(int type, const char * host, long port) = 0;
    virtual int set_term(const char * text) = 0;
    virtual int set_term(const wchar_t * text) = 0;
    virtual int get_phon(std::vector<std::string> & phons) = 0;
... // omitted it's too long
};

次に、プラグインに次のようなインターフェイスを実装するクラスがあります。

class RWD_PLUGIN_API _rwd_dictcn_t : public _rwd_autocomplete_plugin_base_t
{
public:
    _rwd_dictcn_t();
    ~_rwd_dictcn_t();
... // details of implementation omitted

プラグインの作成者は次のように定義されます。

EXTERN_C int RWD_PLUGIN_API create_rwd_plugin(_rwd_plugin_base_t ** pp)
{
    *pp = new _rwd_dictcn_t();
    return OK;
}

最後に、メイン アプリケーションでクリエーターを使用して、次のようにプラグインを使用します。

...
    lt_dlhandle lh = lt_dlopen(filePath);
        RWD_PLUGIN_CREATE_FUNC_T pPluginFunc = NULL;
        if(lh)
        {
            pPluginFunc = reinterpret_cast<RWD_PLUGIN_CREATE_FUNC_T>(lt_dlsym(lh, "create_rwd_plugin"));

            if(pPluginFunc)
            {
                RWD_PLUGIN_BASE_T * pBase = NULL;
                if(OK == (*pPluginFunc)(&pBase))
                {
                    RWD_PLUGIN_TYPE_T pluginType = pBase->get_plugin_type();
                    if(pluginType == RWD_PLUGIN_TYPE_AUTOCOMPELE)
                    {
...
                        RWD_PLUGIN_FUNC_T pPluginInitFunc = reinterpret_cast<RWD_PLUGIN_FUNC_T>(lt_dlsym(lh, "initialize_rwd_plugin"));
                        if(pPluginInitFunc)
                            (*pPluginInitFunc)(NULL);

                        //  set proxy
                        RWD_AUTOCOMPLETE_PLUGIN_BASE_T * pAuto = dynamic_cast<RWD_AUTOCOMPLETE_PLUGIN_BASE_T*>(pBase);

...

問題は、dynamic_cast が常に失敗し、pAuto が nil になることです。ただし、WIN32 バージョンは正常に動作します。Linux で autoconf2.61 automake1.10.1 make3.81 g++4.4.4 libtool1.5.26 で問題が発生しました。私は Linux プログラミングの経験が少ないので、ここで助けを得たいと思っています。ありがとう!

完全なソース コードは、必要に応じて Sourceforge で入手できます: svn co https://rdwtwdb.svn.sourceforge.net/svnroot/rdwtwdb rdwtwdb

4

2 に答える 2

1

-Wl,--export-dynamicリンカー引数を使用してビルドしてみてください。同様の動作に遭遇したときに、この引数が必要だったことを思い出します。

于 2010-07-13T14:22:39.443 に答える
0

問題はプライベート継承である可能性があります:

_rwd_autocomplete_plugin_base_t : _rwd_plugin_base_t

また、仮想関数があるため、型はすでにポリモーフィックですが、仮想デストラクタを追加しても害はないと思います。

編集:申し訳ありませんstructが、デフォルトの継承がパブリックであるため、そこで使用していることに気付きました。ただし、特にコンパイラ間の違いが見られるため、明示するのがおそらく最善です。

于 2010-07-13T12:57:53.400 に答える