この件に関して見つけたすべてのチュートリアルを何日も読んで読み直し、SO で関連する質問を何時間も (さらには何日も) 閲覧しましたが、まだ次のことを行うことができません。これが重複している場合は、申し訳ありません。重複した質問を何度も見て再読した可能性がありますが、私の問題に対する回答の関連性を理解できませんでした。それはさておき...
アプリケーションにプラグイン アーキテクチャを実装しようとしています。プラグインはコンパイルされ、ライブラリとしてインストールされます。実行時に、アプリケーションは dlopen() / dlsym() を使用して、プラグインの関数をロードおよびリンクします。
プラグイン (ライブラリ) が一連の関数を実装して、データをメインのアプリケーションに返したり、アプリケーションから渡されたデータを操作したりするという考え方です。
このアイデアをテストするために、プラグイン自体の (人間が読める) 名前を (std::string として) 返す関数を (プラグイン内に) 実装しようとしました。簡単に始められると思いました.... :-/
これが私がこれまでに得たものです:
// Plugin.cpp
extern "C" void plugin_name(std::string *name) {
name = new std::string("Example plugin name");
}
// Application.cpp
void* handle = dlopen("libplugin.so", RTLD_LAZY);
typedef void (*plugin_t)(std::string*);
dlerror(); // Reset errors.
plugin_t call_plugin_name = (plugin_t) dlsym(handle, "plugin_name");
// ... Some error handling code.
std::string my_plugin_name;
call_plugin_name(&my_plugin_name);
dlclose(handle);
// More code that displays my_plugin_name.
プラグイン名が返される、より単純に見える(しかしうまく機能しなかった)ものを含め、さまざまな組み合わせを試しました。
// Plugin.cpp
extern "C" std::string plugin_name(void) {
return std::string("Example plugin name");
}
コードがコンパイルされ、アプリケーションがクラッシュしなくなりました ;)
しかし、実際のプラグイン名が表示されるはずの場所に空白があります。
これまでに読んだすべてのチュートリアルでは、データが双方向に渡されるメカニズムについて非常に簡単に説明しています: プラグイン <=> アプリケーション。「単純な」 std::string でやろうとしていることは、後でもっと複雑なオブジェクトでやりたいと思います (つまり、プラグイン関数は参照によってオブジェクトを取得し、そのプロパティの一部を変更します)。チュートリアルは多かれ少なかれすべて dlsym() を使用してポインターを作成する時点で停止し、このポインターの使用方法について多くの例を示していません。
それで、それをすべて行う方法は?
別の関連する質問: アプリケーションとプラグインの両方で使用する共通ヘッダーを使用する必要がありますか? 関数呼び出しの署名を定義する場所はどこですか? どうすればこれを行うことができ、それはどのように役立ちますか?