ライブラリ

2000.11.30 作成
2000.12.05 修正

例題をダウンロードする

今回はライブラリの作成を行う。その例題として簡単なクラスライブラリを取り上げる。

クラスライブラリの作成

 クラスライブラリの例として簡単なモジュールクラスを取り上げる。 モジュールクラスは EXE と DLL をサブクラスとして含むクラスである。 まず基底クラスであるモジュールクラスを定義する。
----[wpmod.h]----
 
class wpModule{
  protected:
    HINSTANCE handle;
  public:
    wpModule(HINSTANCE h=NULL){handle=h;}
    HINSTANCE getHandle()  { return handle; }
    HINSTANCE operator()() { return handle; }
    HACCEL loadAccel(const char* acname)
                { return  LoadAccelerators(handle, (LPSTR)acname); }
     };

extern wpModule* Module;
 handle はモジュールを識別するインスタンスハンドル、 Module は自分自身を指すポインタである。 loadAccel はアクセラレーターキーのロードを行う。 リソースのロードはEXE と DLLで共通なので、基底クラスで宣言する。
ここで使うモジュールクラスは次の本に出ていたものを簡略化したものである。

「Windowsオブジェクト指向プログラミング Windows++」
(Paul DiLascia著 翔泳社 ¥6,800)

DLL クラスの作成

次に DLL サブクラスを定義する。
----[wpdll.h]----

class wpDll:public wpModule{
  private:
    friend BOOL WINAPI DllMain(HINSTANCE , DWORD , LPVOID );
    void startup0(HINSTANCE h);
 
    BOOL startup (LPVOID lpvReserved);// ユーザー定義
    BOOL terminal(LPVOID lpvReserved);// ユーザー定義
    };

extern wpDll Dll;
friend 宣言は private メンバーにアクセスするための おまじないで、 startup0 は必須の初期化処理である。
----[wpdll.cpp]----

#include <windows.h>
#include "wpmod.h"
#include "wpdll.h"

wpModule* Module=NULL;
wpDll  Dll;

void wpDll::startup0(HINSTANCE h)
{
  Module=this;
  handle=h;
  }

BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpvReserved)
{
  switch (fdwReason){
    case DLL_PROCESS_ATTACH:
      Dll.startup0(hInstance);
      return Dll.startup( lpvReserved);
    case DLL_PROCESS_DETACH:
      return  Dll.terminal(lpvReserved);
    case DLL_THREAD_ATTACH:
      break;
    case DLL_THREAD_DETACH:
      break;
    }
  return TRUE;
  }

 DLL がロードされるとき、まず startup0 が呼ばれる。 startup0 でハンドルと自分自身のポインタを設定する。
次に はユーザー定義の startup が呼ばれる。 ユーザーは必要に応じて初期化処理を行う。 startup が FALSE を返した場合は DLL はアンロードされる。
 DLL がアンロードされるとき、ユーザー定義の terminal が呼ばれる。 ユーザーは必要に応じて後処理を行う。

 前回作成した DLL を今回のクラスライブラリで書き直したのが test4dll.cpp である。 以下のように入力すれば DLL が作成される。

MAKE /f makedll

----[test4dll.cpp]----


#include <windows.h>
#include "wpmod.h"
#include "wpdll.h"

extern "C"{
int   WINAPI _declspec(dllexport)  TestFunc2(int arg1,int arg2);
 };

int   _declspec(dllexport) TestFunc1(int arg1,int arg2)
{
  return (arg1-arg2);
  }

int   WINAP _declspec(dllexport) TestFunc2(int arg1,int arg2)
{
  return (arg1-arg2);
  }

// FALSE を返すと DLL は Unload される
BOOL wpDll::startup(LPVOID lpvReserved){
  return TRUE;}

BOOL wpDll::terminal(LPVOID lpvReserved ){
  return TRUE;}



EXE クラスの作成

次に EXE サブクラスを定義する。
----[wpapp.h]----

class wpApp:public wpModule{
  private:
    friend int PASCAL WinMain(HINSTANCE , HINSTANCE ,LPSTR , INT );
    void startup0(HINSTANCE);
    int run();

    int startup(LPCSTR);//  ユーザー定義
    int main(INT );     //  ユーザー定義
    int terminal(int);  //  ユーザー定義

    void MsgTransaction(MSG&msg);
    HACCEL KeyAccel;
  public:
    };

extern wpApp App;
----[wpapp.cpp]----


#include <windows.h>
#include "wpmod.h"
#include "wpapp.h"

wpModule* Module=NULL;
wpApp near App;

void wpApp::startup0(HINSTANCE hi)
{
  Module=this;
  handle=hi;
  KeyAccel=loadAccel("KeyAccel");
  }

void wpApp::MsgTransaction(MSG&msg)
{
  BOOL tflag=FALSE;//処理済み

  if(KeyAccel)  tflag=TranslateAccelerator(msg.hwnd,KeyAccel,&msg);
  if(tflag) return;

  TranslateMessage(&msg);
  DispatchMessage(&msg);
  }

int wpApp::run()
{
  MSG msg;
  
  while (GetMessage(&msg,NULL,0,0))  MsgTransaction(msg);
  return msg.wParam;
  }

//******************************************************************
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
{
  int rc;

  App.startup0(hInstance);
  rc=App.startup(lpCmdLine);
  if(rc==0) rc=App.main(nCmdShow);
  if(rc==0) rc=App.run();
  rc=App.terminal(rc);
  return rc;
  }
startup0 は DLL クラスと同様にハンドルと自分自身のポインタを設定し、 次にアクセラレータをロードする。
run はメッセージループの処理を行い、最後に WM_QUIT のパラメータを返す。
 前回の例題を今回のクラスライブラリで書き直したのが test4.cpp である。 以下のように入力すれば EXE が作成される。

>MAKE /f makeapp

----[test4.cpp]----

#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <string.h>
#include <stdio.h>
#include "test4res.h"
#include "wpmod.h"
#include "wpapp.h"
/*<---------------------------------------------------------------------->*/
HWND hwndMain;		//Main window handle

(途中省略)

//*****************************************************************
//*** ユーザー定義ルーチン *****************************************
//*****************************************************************
int wpApp::startup(LPCSTR cmdline){return 0;}

int wpApp::main(INT nCmdShow)
{
  if (!InitApplication())return -1;

  if ((hwndMain = Createtest4WndClassWnd()) == (HWND)0) return -1;
  ShowWindow(hwndMain,nCmdShow);
  return 0;}

int wpApp::terminal(int rc){return rc;}
startup はコマンドラインの処理を行う。
main では メインウインドウの作成と表示を行っている。
terminal ではユーザー定義の終了処理を行う。

ライブラリの作成

作成したクラスライブラリは再利用するためにライブラリ化する。 ライブラリ化にはTLIB.EXEを使用する。 DOS 窓から以下のように打ち込んで、 wpapp.lib と wpdll.lib を作成する。

>MAKE /f makelib

作成したライブラリを使用する場合には makeapp2 makedll2 を使って EXE と DLL を作成する。

修正履歴

初期化のルーチンが LibMain になっていたのを DllEntryPoint に修正。 Visual C と同じだと勘違いしていた。

外部公開名にアンダースコアが付かないようにするために、 以前はコンパイラオプションで -u- を指定していたが、 これだと C のライブラリ関数の呼び出しができなくなる副作用があるので、 WINAPI を付ける方法に変更した。

DLL 外部公開名にアンダースコアが付かないようにするために、 以前はコンパイラオプションで -u- を指定していたが、 これだと C のライブラリ関数の呼び出しができなくなる副作用があるので、 WINAPI を付ける方法に変更した。

2000.12.05 修正
前へ 目次へ