2006-02-01-02-class DLL - 2 - project-enigma

2006-02-01-02-class DLL - 2

>> Site top >> weblog >> 月別アーカイブ >> 2006年02月のlog >> 2006-02-01-02-class DLL - 2

最終更新日付:2014/01/02 00:00:00


class DLL - 2

2006 年 02 月 01 日

さて、今回は DLL ラッパークラスのカラクリについて書いてみよう。前回書いたような使い方を実現するためには、SampleDLL クラスは以下のようになっていればいいことになる。

class SampleDLL {
private:
    typedef int (*FooT)( int, const char* );
    typedef void (*BarT)( int );
public:
    SampleDLL( );
    ~SampleDLL( );
public:
    const FooT Foo;
    const BarT Bar;

...と、こうなっていれば、SampleDLL のオブジェクトに対して Foo( ) や Bar( )が呼び出せるわけだな。そして、これらの const な関数ポインタメンバを初期化するのは当然コンストラクタでやるべきことだ。しかし、const メンバである以上、コンストラクタの初期化リストで指定せねばならん。関数ポインタメンバが public である以上、const メンバにしないわけにはいかない。ここで問題が発生する。const メンバを初期化するよりも前に DLL をロードしなければならないのだ。これをどうするか。クラスのメンバよりも先に初期化されるもの。それは基底クラスだ。そう、それが答えだ。

というわけで、DLLBase クラスを用意する。こいつはコンストラクタとデストラクタでDLL のロードと開放をする。そして、派生クラス向けに関数ポインタのアドレスを取得するメンバ関数を用意...と。インプレは省略。

class DLLBase {
private:
    HINSTANCE m_handle;
public:
    DLLBase( const char* pDLLName );
    ~DLLBase( );
protected:
    void* GetProc( const char* pProcName );
};

で、この DLLBase クラスから SampleDLL を派生すれば、SampleDLL のコンストラクタは以下のように書ける。これなら関数ポインタメンバが初期化される時点では DLL のロードが完了していると前提できる。

SampleDLL::SampleDLL( ) : DLLBase( "Sample.dll" ),
                          Foo( (FooT)GetProc( "Foo" ) )
                          Bar( (BarT)GetProc( "Bar" ) ) { }

基底クラス DLLBase で DLL のロードに失敗したら? 一般に、DLL のロードや関数アドレスの取得で発生するエラーはアプリケーションレベルでは致命的とみなしてよいものだ。だから、これらのクラスはエラーを検出すると例外を投入する...と。こうなっていれば、SampleDLL クラスのインスタンスの生成に成功すればすなわち DLL 関数が利用可能であることが保証されるわけだ。

...さて、基本的なカラクリは説明したかな。今日はこの辺で。

 

コメント

このページにコメントする

 

このページのタグ

Page tag : 開発

 

 


Copyright(C) 2005-2017 project-enigma.
Generated by CL-PREFAB.