DOAP2023開発日記 #8
最初の一歩
ようやく、#8にしてようやく、C++コードの第一歩を踏み出す。
まずは、次のコードをビルドできるようにする。
// doap_global.h
#ifndef DOAP_GLOBAL_H
#define DOAP_GLOBAL_H
#include <QtCore/QtGlobal>
#define DOAP_EXPORT extern "C" Q_DECL_EXPORT
#endif // DOAP_GLOBAL_H
// main.cpp
#include "doap_global.h"
#include <dsapi.h>
#include <QString>
/**
* @brief フィルターアドインインストール時に呼ばれる関数
* @param pInitData 初期化データ構造体へのポインタ
* @return インストール結果を渡す
*/
DOAP_EXPORT uint FilterInit(FilterInitData *pInitData) {
pInitData->appFilterVersion = kInterfaceVersion;
pInitData->eventFlags = kFilterAny;
qstrcpy(pInitData->filterDesc, "DOAP2023");
return kFilterHandledEvent;
}
/**
* @brief イベントごとにフックされるエキスポート関数
* @param pContext DSAPIコンテキストへのポインタ
* @param eventType イベントタイプ
* @param ptr イベントタイプごとのデータへのポインタ
* @return 処理済みならkFilterHandledEvent、未処理ならkFilterNotHandledを渡す
*/
DOAP_EXPORT uint HttpFilterProc(
FilterContext *pContext,
uint eventType,
void *ptr
) {
return kFilterNotHandled;
}
HTTPタスクに組み込むアドインでは、FilterInitとHttpFilterProcの2関数をエキスポートする必要がある。各関数はそれぞれ、DOAP_EXPORTが付いているが、これはWindowsの場合、次のように展開される。
// DOAP_EXPORT (win32)
extern "C" __declspec(dllexport)
C++のプログラムでは、リンク名がマングリングにより元の名前が変更されてしまうため、HTTPタスクが認識できなくなるので、「extern "C"」の付与が必須になる。
FilterInitData構造体
FilterInitData構造体は、Notes C APIのdsapi.hヘッダファイルで次のように定義されている。
typedef struct {
unsigned int serverFilterVersion;
unsigned int appFilterVersion;
unsigned int eventFlags;
unsigned int initFlags;
char filterDesc[ kMaxFilterDesc + 1 ];
} FilterInitData;
ここで、serverFilterVersion、initFlagsは無視する。
appFilterVersionには、同ヘッダ内に定義されているkInterfaceVersionの値をそのまま入れる。
eventFlagsには、フィルタリングする(=フックされて呼ばれる)イベント定数の和を設定する。kFilterAnyはすべてのフィルタリングを有効にしてくれる。ここで指定したイベントが発生するたびに、HttpFilterProc関数が呼ばれ、引数のeventTypeに、イベントの種類がわかるようになっている。
filterDescには、HTTPタスクがDSAPIアドインをロードした結果を表示する際に、コンソールに表示するための文字列を指定する。
インストール
こうしてできたDLLへのパスを、Dominoディレクトリのサーバー文書、またはWebサイト文書のDSAPIの項目で設定すればよい。
DOAP DLLはQtのCoreライブラリに依存するので、DOAP DLLと同じ場所にQt5Core.dllを配置すればいい。
Qtライブラリが依存するMSVCのライブラリは、Windowsに含まれていなければ、マイクロソフト公式の再頒布可能パッケージをインストールすればいい。
なお、私はGulpタスクランナーでビルドとインストーラ作成を一発で作成できるようにしている。
これでDominoサーバを起動して、以下のようなメッセージが表示されればひとまず成功となる。
なお、前述のコードで、HttpFilterProcではどんなイベントが発生しても「kFilterNotHandled」を返す以外のことをしていないので、このアドインは実際には何もしないことになる。
まとめ
DSAPIを用いたHTTPタスクアドインは、HTTPタスクがおこなっている、Http/Httpsリクエストを受け付けてから、Httpレスポンスを返すまでを8つ前後の段階でフィルタリング(フック)するので、仕組みを垣間見ることができる上、一般的なWebサーバと違った、Dominoデータベースのリソースにマッピングするプロセスもあるので、非常に興味深い。