見出し画像

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サーバを起動して、以下のようなメッセージが表示されればひとまず成功となる。

「DSAPI DOAP2023 Loaded successfully」

なお、前述のコードで、HttpFilterProcではどんなイベントが発生しても「kFilterNotHandled」を返す以外のことをしていないので、このアドインは実際には何もしないことになる。

まとめ

DSAPIを用いたHTTPタスクアドインは、HTTPタスクがおこなっている、Http/Httpsリクエストを受け付けてから、Httpレスポンスを返すまでを8つ前後の段階でフィルタリング(フック)するので、仕組みを垣間見ることができる上、一般的なWebサーバと違った、Dominoデータベースのリソースにマッピングするプロセスもあるので、非常に興味深い。

この記事が気に入ったらサポートをしてみませんか?