![]() |
latest release v1.8.11 - last update Mon Oct 25 2021 |
前処理doxygenの入力に使うソースファイルは、組込のC言語プリプロセッサによって解析します。 デフォルトでは、部分的な前処理しかしません。つまり、条件付コンパイル構文(#ifのような)と、マクロ定義は評価しますが、マクロ展開はしません。 ですので、次のようなコード断片があると、 #define VERSION 200 #define CONST_STRING const char * #if VERSION >= 200 static CONST_STRING version = "2.xx"; #else static CONST_STRING version = "1.xx"; #endif doxygenは、以下のようにパーサーに渡します。 #define VERSION #define CONST_STRING static CONST_STRING version = "2.xx"; 前処理を全部無効にするには、設定ファイルで、ENABLE_PREPROCESSING を static CONST_STRING version = "2.xx"; static CONST_STRING version = "1.xx";
#define VERSION #define CONST_STRING static const char * version = "1.xx"; となります。 このとき、doxygenは すべて のマクロ定義を展開します(必要なら再帰的に)。 しかし、これでは過剰なことも多いです。 ですので、明示的に指定したdefineのみを展開するよう指示することもできます。 それには、EXPAND_ONLY_PREDEF を 前処理時点でヘルプが必要となる典型的な例があります。それは、Microsoft の言語拡張 declspec と、GNU の __attribute 拡張です。前者の例です。 extern "C" void __declspec(dllexport) ErrorMsg( String aMessage,...); 何もしないと、doxygenは混乱し、__declspec をある種の関数とみなします。この場合、次のようにします。 ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES PREDEFINED = __declspec(x)= こうすると、__declspec(dllexport) が、ソースコードを解析する前に、確実に取り除かれます。 さらに複雑な例として、 /*! IID への参照 */
#ifdef __cplusplus
#define REFIID const IID &
#else
#define REFIID const IID *
#endif
/*! IUnknown インターフェース */
DECLARE_INTERFACE(IUnknown)
{
STDMETHOD(HRESULT,QueryInterface) (THIS_ REFIID iid, void **ppv) PURE;
STDMETHOD(ULONG,AddRef) (THIS) PURE;
STDMETHOD(ULONG,Release) (THIS) PURE;
};
マクロを展開しないと、doxygenは混乱してしまうでしょう。しかし、REFIIDマクロは展開したくないところです。ドキュメントがついていますし、ドキュメントを読んだユーザは、インタフェースを実装する際に使うことになるからです。 設定ファイル内で次のように設定すれば、 ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
PREDEFINED = "DECLARE_INTERFACE(name)=class name" \
"STDMETHOD(result,name)=virtual result name" \
"PURE= = 0" \
THIS_= \
THIS= \
__cplusplus
次のように、適切な結果がdoxygenパーサーに与えられます。 /*! IID への参照 */
#define REFIID
/*! IUnknown インターフェース */
class IUnknown
{
virtual HRESULT QueryInterface ( REFIID iid, void **ppv) = 0;
virtual ULONG AddRef () = 0;
virtual ULONG Release () = 0;
};
ここで、PREDEFINED タグは、関数形式のマクロ定義( また、通常はプリプロセッサが自動的に定義するプリプロセッサ定義( 場合によっては、マクロ名や関数を他のもので置き換えて、その結果をマクロ置換えさせたくないこともあるでしょう。これを行うには、 例えば、次のようなコードがあるとします。 #define QList QListT
class QListT
{
};
QListクラスのクラス定義としてdoxygenに解釈させる方法は、以下のようにdefineするしかありません。 PREDEFINED = QListT:=QList 次は、Valter Minute と Reyes Ponce から提供された例です。これで、MicrosoftのATL & MFC ライブラリの定型コードを読み進むことが可能なように、doxygenをサポートしてくれます。 PREDEFINED = "DECLARE_INTERFACE(name)=class name" \
"STDMETHOD(result,name)=virtual result name" \
"PURE= = 0" \
THIS_= \
THIS= \
DECLARE_REGISTRY_RESOURCEID=// \
DECLARE_PROTECT_FINAL_CONSTRUCT=// \
"DECLARE_AGGREGATABLE(Class)= " \
"DECLARE_REGISTRY_RESOURCEID(Id)= " \
DECLARE_MESSAGE_MAP= \
BEGIN_MESSAGE_MAP=/* \
END_MESSAGE_MAP=*/// \
BEGIN_COM_MAP=/* \
END_COM_MAP=*/// \
BEGIN_PROP_MAP=/* \
END_PROP_MAP=*/// \
BEGIN_MSG_MAP=/* \
END_MSG_MAP=*/// \
BEGIN_PROPERTY_MAP=/* \
END_PROPERTY_MAP=*/// \
BEGIN_OBJECT_MAP=/* \
END_OBJECT_MAP()=*/// \
DECLARE_VIEW_STATUS=// \
"STDMETHOD(a)=HRESULT a" \
"ATL_NO_VTABLE= " \
"__declspec(a)= " \
BEGIN_CONNECTION_POINT_MAP=/* \
END_CONNECTION_POINT_MAP=*/// \
"DECLARE_DYNAMIC(class)= " \
"IMPLEMENT_DYNAMIC(class1, class2)= " \
"DECLARE_DYNCREATE(class)= " \
"IMPLEMENT_DYNCREATE(class1, class2)= " \
"IMPLEMENT_SERIAL(class1, class2, class3)= " \
"DECLARE_MESSAGE_MAP()= " \
TRY=try \
"CATCH_ALL(e)= catch(...)" \
END_CATCH_ALL= \
"THROW_LAST()= throw"\
"RUNTIME_CLASS(class)=class" \
"MAKEINTRESOURCE(nId)=nId" \
"IMPLEMENT_REGISTER(v, w, x, y, z)= " \
"ASSERT(x)=assert(x)" \
"ASSERT_VALID(x)=assert(x)" \
"TRACE0(x)=printf(x)" \
"OS_ERR(A,B)={ #A, B }" \
__cplusplus \
"DECLARE_OLECREATE(class)= " \
"BEGIN_DISPATCH_MAP(class1, class2)= " \
"BEGIN_INTERFACE_MAP(class1, class2)= " \
"INTERFACE_PART(class, id, name)= " \
"END_INTERFACE_MAP()=" \
"DISP_FUNCTION(class, name, function, result, id)=" \
"END_DISPATCH_MAP()=" \
"IMPLEMENT_OLECREATE2(class, name, id1, id2, id3, id4,\
id5, id6, id7, id8, id9, id10, id11)="
doxygenのプリプロセッサがいかにパワフルかお分かりかと思いますが、さらに自由度が必要なら、いつでも入力フィルタを書いてそれを INPUT_FILTER の後に指定できます。 前処理の効果に不安をお持ちなら、次のように実行してみてください。 doxygen -d Preprocessor これによってdoxygenは、前処理を実行した後の入力ソースを標準出力にダンプします。(ヒント:他の出力を無効にするには、設定ファイルで、 |
|
|
This page was last modified on Mon Oct 25 2021.
© 1997-2021 Dimitri van Heesch, first release 27 oct 1997.
© 2001 OKA Toshiyuki (Japanese translation). © 2006-2021 TSUJI Takahiro (Japanese translation). © 2006-2014 TAKAGI Nobuhisa (Japanese translation). |