共有ライブラリから関数呼び出し
プログラムの部品を共有ライブラリ(DLLなど)として分けると便利なことがあります。
なぜ便利かというと動的に関数やオブジェクトを呼び出せるからです。
これは静的リンクと違って関数やオブジェクトが実際にあるかどうかは気にしなくていいということになります。
そこでQTには共有ライブラリで関数を楽に扱うためにQLibraryが用意されています。
使い方
では、実際の使い方を簡単に紹介します。
例としてここでは次の構成を持つ2つのプロジェクトを作ったとします。
Utilsが共有ライブラリ、MOCが共有ライブラリを使う側のプロジェクトです。
まず、Utilsプロジェクトで関数だけを定義したfunc.cppというファイルを作りました。
func.cpp#include "utils_global.h" #include <iostream> #ifdef Q_OS_WIN #define MY_EXPORT __declspec(dllexport) #else #define MY_EXPORT #endif extern "C" MY_EXPORT void sayHello(int count) { while(--count){ fprintf(stdout, "Hello!!"); } }
ここで定義した関数を別のプロジェクトから共有ライブラリ経由で呼び出します。
QLibraryから呼び出したい関数は必ずC言語としてグローバルなところに定義してください。
なぜこうするかというとQLibraryでマングリングしていない名前(元の名前)から関数を呼び出すためです。
さらにWindows環境ではDLLから関数を呼び出すのに __declspec(dllexport) を使わなければならないみたいです。
あとは共有ライブラリをつくればライブラリ側の設定は完了です。
次にライブラリを使う側のプロジェクト(MOC)のmain.cppで共有ライブラリから関数を呼び出してみます。
main.cpp#include <QApplication> #include <QLibrary> int main(int argc, char * argv[]) { QApplication a(argc, argv); QLibrary lib("Utils"); lib.load(); ///ライブラリ呼び出し typedef void (*SayHelloFunc)(int); ///呼び出したい関数 SayHelloFunc func = (SayHelloFunc)lib.resolve("sayHello"); ///共有ライブラリから関数取得 if(func != 0) func(10); return a.exec(); }
QLibraryのコンストラクタには.dllのような拡張子がつかないライブラリ名だけ渡すだけでOKです。
そして、ライブラリの読み込みにはloadを実行します。
その後、resolveで関数名を渡して、もし関数が見つかれば関数ポインタが返ってくるので関数が実行できます。
もし関数名が間違っていたり、型が間違っていれば0が返ってきます。
もし関数内でグローバル変数が変更されたらその値は次の関数を呼び出したときも値の変化は保持し続けられるようです。
まとめ
以上の手順を簡単にまとめるとこうなります。
- 共有ライブラリにC言語としてグローバルな関数を作る。
- 共有ライブラリを作る。
- 呼び出す側のプロジェクトに共有ライブラリをコピーする。
- QLibraryを使って関数呼び出し
以上が共有ライブラリから関数呼び出しする手順です。お疲れ様でした!