これは、SDL Users Mailing Listに投稿された 「SDL 1.3 Coding Guide」 (Message-Id: E154O63-0005RF-00@roboto.devolution.com)の和訳です。 原文: http://mail.lokigames.com/ml/sdl/14088.html 原文はマルチパートですが訳出時に1つのテキストファイルとしました。 datatype と attribute まわりの訳がいまひとつしっくりこないです。 ご意見お待ちしております.... ----- Zinnia (zinnia@risky-safety.org) http://ee5lance.ee5.yz.yamagata-u.ac.jp/~zinnia/ [和訳始め]---------------------------------------- Ok. SDL 1.3コーディングスタイルについてここでの議論の結果をとりあえず まとめてみました。ただしまだコードは書かれていないし、スタイルが変わる 可能性があることを忘れないでください。 See ya! -Sam Lantinga, Lead Programmer, Loki Software, Inc. SDLライブラリコードを書くための手引 - Sam Lantinga, May 28, 2001 ================================================================ 目次: - ライセンス - 言語 - データ型 - フォーマット - API規約 - デバッグ - 例 ライセンス ========== SDLはGNU Library General Public License(ママ)で公開されています。 ライセンスの全文は"COPYING"ファイルにあります。また http://www.gnu.org/copyleft/lgpl.html で読むこともできます。 SDLコードに対するすべてのパッチや寄贈されたコード(contributions)も このライセンスの支配下に置かれます。 言語 ==== SDLは厳密なANSI Cで書かれていますので、多くのプラットホームで コンパイルでき、たくさんの言語で使うことができます(binding)。 APIは「extern "C"」で宣言されていますので、C++から直接呼び出すことが できます。 可能な限り、SDLコードはgcc -Wall -ansi -pendaticでコンパイルしたときに 警告(warnings)を出さないように努力します。警告は潜在的なバグや 移植性のないコードの存在を示しているからです。 プラットホーム独立なSDLコードは、システムヘッダ(訳註: プラットホームに 依存したヘッダ)を直接含んではいけません。コードがスタンダードCライブラリに 依存しているなら、"SDL_stdlib.h"をインクルードするべきです。 SDL_stdlib.hはstdlib.h、string.h、ctype.hをインクルードし、さらに NULLを((void *)0)と定義します。 コードがこれら以外の関数に依存しているなら、それはもうポータブルとは 言えませんのでそれらの関数のポータブルな実装をインクルードする べきです(訳註: wrapperを用意するとか、deviceのsubdirectory側に振るとか?) 静的な関数は性能向上のため__inline__キーワードを使ってインライン化すると よいでしょう。このキーワードはSDL_stdlib.hで定義されています。 データ型 ======== プラットホーム独立なデータ型はSDL_types.hでまとめて提供されます。 特定のデータ型(datatype)の属性(attribute)が必要なときは いつでもそれらを使うべきです。 システムAPI関数のパラメータには、それに合った正しいデータ型を使う 必要があります。 例: caddr_t, size_t, LPSTR, HANDLE サイズのような、特定の属性を持つ変数を使うときは、SDLが定義した データ型を使います: Sint8 - 符号あり8ビット整数 Uint8 - 符号なし8ビット整数 Sint16 - 符号あり16ビット整数 Uint16 - 符号なし16ビット整数 Sint32 - 符号あり32ビット整数 Uint32 - 符号なし32ビット整数 SDL_string - 文字列、典型的には'char *'または'wchar_t' それ以外の属性を持つ変数にはC本来のデータ型を使います 例: int, unsigned int, char * 浮動小数点数は使うべきではありません。低速なソフトウエアエミュレートに 変換されるアーキテクチャもあるからです。 フォーマット ============ SDLのコードはStroustrupスタイルでフォーマットされます。 タブは4文字幅でスペースに展開されます。空白は可読性を向上させるために 使われるべきです。また、78文字以内におさめるために論理的に 折り返すべきです。 コードはできるだけわかりやすく書かれるべきです。そして、 複雑なコードの前には処理の内容を説明するコメントがあるとよいでしょう。 各々の関数プロトタイプは、戻り値、引数、driver非依存のエラーコードで 構成されたドキュメント部を持ちます。また、スレッド安全性(thread-safety)に 関する注意事項も記述される予定です。ドキュメント部は、ツールのパースを 簡潔にするために、/** で始まるコメントとなります。 API規約 ======= SDL関数は"SDL_"という接頭語をもち、失敗することがないなら何も返さず、 そうでないならSDL_statusというステータスコードを返します。 ステータスコードは"SDL_status.h"で列挙型として定義されています。 ステータスは、負の値のときは何か失敗している、というように 定義されています。 関数に追加の説明をつけるとき、引数のデータタイプの説明へのポインタを 含めるべきです。(訳註: 下の例では@seeにあたるものと思われる) 例: /** SDL_CreateObject - create a new object of some type @param object A pointer to an object handle, set to point to the new object @param flags A flag parameter controlling object creation @return SDL_status この関数はある型のオブジェクトを生成します。このオブジェクトを 受け入れる他の関数とともに使うことができます。この関数に関係ない 註釈を入れないでください(訳註: 具体的にどういう関数とともに 使うのか、といった説明でしょうか?) X、Y、Zに注意してください。あなたを驚かせることがあります。 架空の関数についての説明を書くことがどのくらい無意味なことでしょうか? Thread-safe: yes (or: no, グローバルデータにアクセスするとき) @see SDL_status, SDL_object **/ SDL_status SDL_CreateObject(SDL_object* *object, Uint32 flags) { SDL_status status = SDL_OKAY; object_state state; SDL_object *new_object; /* This comment adds clarity to the code */ status = internal_function(&state, flags); if ( status < 0 ) { return status; } /* * Note that C++ style comments are not allowed by some compilers. * Also, keep the code formatted to 78 characters if possible. */ if ( (status=condition_one(&state)) == SDL_OKAY) && (status=condition_two(&state)) == SDL_OKAY) ) { new_object = create_simple_object(&state, flags); if ( new_object ) { add_additional_info(new_object, flags); *object = new_object; } else { status = SDL_STATUS_OUTOFMEMORY; } } return status; } デバッグ ======== 単純なステータスコードよりももっと多くのデバッグ情報を アプリケーションに渡したいときは、SDL_DEBUG()を使うことができます。 これは"SDL_debug.h"で定義されているマクロで、デフォルトで有効になって おり、以下のようなプロトタイプの関数を宣言します: void SDL_debug(SDL_debugtype, SDL_debuglevel, const char *file, int line, const char *fmt, ...); SDL_debugtypeは列挙型で、メッセージを生成するサブシステムを指定します。 サブシステムを指定しないときは、SDL_DEBUG_GENERALを利用します。 SDL_debuglevelは列挙型で、メッセージの重要度を指定します。 SDL_DEBUG_ERROR, SDL_DEBUG_WARNING, SDL_DEBUG_MESSAGEのいずれかです。 'file' はメッセージを生成しているソースファイル名を指定します。 __FILE__プリプロセッサ命令を指定するとよいでしょう。 'line' はソースファイル中の行を指定します。__LINE__プリプロセッサ 命令を指定するとよいでしょう。 残りの引数はstdargフォーマットメッセージが来ます (訳註: printfとかと一緒)。メッセージは1Kバイトまでで、改行、 特殊文字が入ってはいけません。 SDL_debug()はデバッグメッセージを構成し、コールバック関数に渡します。 コールバック関数はSDL_SetDebugCallback(callback)で指定できます。 コールバック関数のプロトタイプ宣言は以下の通りです: void callback(SDL_debugtype, SDL_debuglevel, const char *file, int line, const char *message); SDL_DEBUG() の使いかたの例: if ( non_fatal_condition() ) { SDL_DEBUG(SDL_DEBUG_GENERAL, SDL_DEBUG_WARNING, __FILE__, __LINE, "A non fatal condition was encountered: 0x%x", state); } SDL_TRACE()マクロもデバッグのために使うことができます。これも "SDL_debug.h"で定義されています。SDL_TRACE()はトレースレベルを あらわす数値と、メッセージをうけとります。このマクロはSDLライブラリが 指定されたトレースレベルよりも大きい値でビルドされていたときのみ 実行されます。このマクロはSDL_debug()を、SDL_DEBUG_GENERAL、 SDL_DEBUG_TRACE、現在のファイル、行、で呼びだします。 SDL_TRACE() の使いかたの例: SDL_TRACE(1, "Entering debug area, watch your step"); if ( everything_ok() ) { SDL_TRACE(3, "Proceeding normally"); } else { SDL_TRACE(2, "Special condition, resetting and retrying"); }