【C++】DLL明示的動的読み込み【ちょっとだけ簡単にしてみた】

【C++】DLL明示的動的読み込み【ちょっとだけ簡単にしてみた】

DLLの読み込み呼び出し使用して関数を使う場合に、暗黙的静的だと、DLLが存在しない場合に何もエラー表示を出さず起動しないし、動的だったらプログラム内に書くだけで読み込めることなどから、DLLの読み込みはどっちかというと動的、明示的に行ったほうがいいのかなと私は思いました。
そこで、DLLを動的に読み込むのを簡単に行えるようにクラスを作ってみました。
LoadLibrary関数とGetProcAddress関数でDLL読み込むのを中でやっているだけなのですが、HSPみたいに、DLL名と関数名を指定するだけで読み込める感がほしかったので、クラス作ってみました。
C++まだ不慣れなもので、ソースコード汚いですがお許しを (汗
もうちょっときれいにかけそうだけどなー…。
2013/03/30 修正
2013/03/31 修正

#include <windows.h>
#include <tchar.h>

class dllload {
private:
  HMODULE hDll;
  bool failed;
public:
  dllload() {
    hDll = NULL;
    failed = false;
  }
  dllload(const TCHAR *dllname) {
    hDll = NULL;
    failed = false;
    uselib(dllname);
  }
  ~dllload() {
     if(hDll != NULL) freelib();
  }
  bool uselib(const TCHAR *dllname) {
    failed = true;
    if(hDll == NULL) {
      if((hDll = LoadLibrary(dllname)) != NULL) failed = false;
    }
    return failed;
  }
  bool getfunc(const char *funcname, void *func) {
    failed = true;
    if(hDll != NULL) {
      if((*((FARPROC*)func) = GetProcAddress(hDll, funcname)) != NULL) failed = false;
    }
    return failed;
  }
  bool freelib() {
    failed = true;
    if(hDll != NULL) {
      if(FreeLibrary(hDll)) {
        failed = false;
        hDll = NULL;
      }
    }
    return failed;
  }
  bool fail() {
    return failed;
  }
};

■DLLの読み込み (1)
dllload hoge;
hoge.uselib(const TCHAR *dllname)
■DLLの読み込み (2)
dllload hoge(const TCHAR *dllname);
■関数の読み込み
hoge.getfunc(const char *funcname, void *func)
■DLLの解放 (省略可。省略時はオブジェクト消滅時に自動で呼ばれる)
hoge.freelib()
■エラーチェック (上らの処理でエラーが発生しているときはtrue、そうでないときにはfalseを返す)
hoge.fail()

使用例

#include <iostream>
using namespace std;

int (*FuncMessageBoxA)(int hWnd, char* lpText, char* lpCaption, unsigned int uType);

int main() {
  // DLLロード
  dllload dll; /* 本来はnew演算子でオブジェクトを作成するべき */
  dll.uselib(_T("USER32.DLL")); /* 別の場所からもDLL読み込める */
  if(dll.fail()) return -1; /* 返り値調べなくてもエラーわかる */
  cout << "DLL読み込み完了" << endl;
  dll.getfunc("MessageBoxA", &FuncMessageBoxA);
  if(dll.fail()) return -1;
  cout << "関数読み込み完了" << endl;
  cout << "----------------" << endl;
  // 関数の使用
  FuncMessageBoxA(0, "ログアウトひゅんひゅん!!", ">∀<┘", 0);
  return 0;
}

windows.hで既にMessageBox定義されてるとかそういうのは気にしない。
本来はtypedefで関数の引数とかを宣言してやるべきなんですけど、どうせプログラム全体で使う関数なら、直接初期化しちゃったほうがいいかなと思い、最初のところでいきなり初期化してます (汗
先ほども書いたように、DLLの解放は自動で行っているので、エラー処理でも最後でも、returnで終わっています。
柔軟な書き方ができるように、オブジェクト定義時にもほかの場所でもDLL呼び出せるし、エラーチェックは返り値からもfail()からも取得できるし、明示的なDLL解放もできれば、DLL解放忘れでも自動で解放してくれます。
DLL解放や呼び出しを2回してしまった場合にも対応。
めっちゃ小規模で誰でもすぐ作れそうなクラスですが、あれば便利だと思います。
ではまたいつか。
↓クリック (投票) お願いします~


「【C++】DLL明示的動的読み込み【ちょっとだけ簡単にしてみた】」への8件のフィードバック

  1. uselibを複数回呼び出した時のことを考えていない。
    fDllの必要性がない。
    c++ならエラー発生時には例外飛ばせばしたほうが。。。

    ライブラリの読み込み(uselib)はコンストラクタで呼び出して、freelibを呼び出したときは処理をしたあとにhDll=NULL。
    エラーが発生したら、適当なエラーを飛ばす。
    getfuncとコンストラクタ、デストラクタのみをpublicに置くべきかと思います

  2. >uselibを複数回呼び出した時のことを考えていない。
    そうですね。すいません。
    >fDllの必要性がない。
    ああ、なるほど。hDLLがNULLかどうかで判断すればよいんですね。
    それなら明示的にfreelibした時でも2重で解放されない。
    >例外飛ばし
    try catch ?

    failはfstreamのパクリです。動的読み込みだと、場合によっては特定のDLLで読み込みに失敗しても処理続行できる場合とかあるし。

    ちょっと作り変えてきます。

  3. >>例外飛ばし
    >try catch ?
    表現が不適切でした。正しくは例外を発生させるですね。
    try,catchです。せっかくc++を使っているので、例外処理を簡素にしたほうが使い勝手がいいような気がしたので。

    それにしてもこのブログ重すぎ。タブレットからでは、とても見れたもんじゃない。

  4. >例外 (ry
    本当は予測できないエラーに対処するためにtry catch使うべきなんですよね…。考えておきます…。

    >ブログ
    私に言われましても…

  5. ちなみに重たいのはこのブログだけですよ。pcでアクセスしても重たいし。表示しているブログパーツのせいでは?

  6. 思いつくとしたら、ブログバナーのGIFアニメかブログランキングのSWFでしょうか…。

    重いとだけ言われましても私の環境だと全部サクサク動くのでわかりません。すいません。

  7. いや、単なるjsのこと言ったるんだけど。pcでページ表示直後のカクつくのが、タブレットではかなり重くなり、応答なしとして扱われる。
    この現象が発生するのはこのブログだけ。他のyahooブログではそんなこと起きない。

  8. そんなこと言われましてもわからないものはわかりません。

コメントは受け付けていません。