ページ 11

classのDLLに動的リンクするとき、直接newキーワードを使うにはどうしたらいいでしょうか

Posted: 2015年10月09日(金) 19:10
by 黒崎圭一
「classのDLLに動的リンクするとき、直接newキーワードを使うにはどうしたらいいでしょうか」

少し前からDLLの作成について学ばせていただいています。

静的リンクでは特に問題を感じられませんでしたが、
やっかいなのは動的リンクでした。

先日やっとclassのDLL化と動的リンクまで間接的ながら成功したのですが
どうも違うような気がしてなりません。

CMyClassというクラスを作成して、(もちろんメソッドはvirtualで)
以下のような全域関数をexportしました。

コード:

extern "C" declspec(dllexport) void __stdcall CreateInstance(void)
{
  return new CMyClass;
}
そして呼び出す側では関数ポインターを定義して
以下のようにクラスにアクセスすることができました。

コード:

typedef void (*PFUNC)(void);
HMODULE hModule = LoadLibrary("MyClass.dll");
PFUNC pFuncCreateInstance = (PFUNC)GetProcAddress(hModule, "CreateInstance");

CMyClass* pClass = pFuncCreateInstance();
/* クラスの使用 */
delete pClass;
しかし、オープライブラリのOpenCVなどで動的リンクを試してみたところ、
以下のように直接的にアクセスすることができました。

コード:

cv::Mat* pMat = new cv::Mat;
CreateInstance()を使った私の方法は何か間違ってるような気がします。
正しい方法がありましたら是非教えて頂きたいたいです。

Re: classのDLLに動的リンクするとき、直接newキーワードを使うにはどうしたらいいでしょうか

Posted: 2015年10月17日(土) 23:17
by lriki
new が使えないとは具体的にどういう状況ですか?(シンボル未定義でリンクエラーが出ている?)
普通はクラス自体をエクスポートすることで使えるようになるはずです。
https://msdn.microsoft.com/ja-jp/library/a90k134d.aspx

あと、CreateInstance()を使う方法自体は間違いではありません。
COMのように互換性の向上や実装の隠蔽のために使うこともあります。
ただ、2つ目のコードのようにDLLの中でnewしたオブジェクトをexe側でdeleteするのは厳禁です。
特にexeとdllを別のコンパイラでビルドした場合など、new と delete の実装がペアになっていないと問題になります。
CreateInstance()を使う場合はペアとなるDeleteInstance()のような関数を用意し、DLLの中で delete キーワードで削除するのが無難です。