4.7 デバッグインターフェース

Lua には組み込みのデバッグ機能がありません。その代わりに関数とフック (hook) を使った特別なインターフェースが用意されています。このインタフェースを使うと、インタープリタの内部情報を必要とするデバッガやプロファイラといったツールを好きなように作成できます。

lua_Debug

typedef struct lua_Debug {
  int event;
  const char *name;           /* (n) */
  const char *namewhat;       /* (n) */
  const char *what;           /* (S) */
  const char *source;         /* (S) */
  size_t srclen;              /* (S) */
  int currentline;            /* (l) */
  int linedefined;            /* (S) */
  int lastlinedefined;        /* (S) */
  unsigned char nups;         /* (u) number of upvalues */
  unsigned char nparams;      /* (u) number of parameters */
  char isvararg;              /* (u) */
  char istailcall;            /* (t) */
  unsigned short ftransfer;   /* (r) index of first value transferred */
  unsigned short ntransfer;   /* (r) number of transferred values */
  char short_src[LUA_IDSIZE]; /* (S) */
  /* private part */
  other fields
} lua_Debug;

関数およびアクティベーションレコード1に関する様々な情報を保存するのに使われるデータ構造です。lua_getstack はこのデータ構造のプライベートな部分だけを埋め、その部分が後で使われます。他のフィールドを埋めるには lua_getinfo を呼びます。

lua_Debug のフィールドは次の意味を持ちます:

lua_gethook

[-0, +0, -]
lua_Hook lua_gethook (lua_State *L);

現在のフック関数を返します。

lua_gethookcount

[-0, +0, -]
int lua_gethookcount (lua_State *L);

現在のフックカウントを返します。

lua_gethookmask

[-0, +0, -]
int lua_gethookmask (lua_State *L);

現在のフックマスクを返します。

lua_getinfo

[-(0|1), +(0|1|2), m]
int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);

特定の関数あるいは関数呼び出しに関する情報を取得します。

関数呼び出しに関する情報を入手するには、パラメータ ar を有効なアクティベーションレコードとして呼び出します。有効なアクティベーションレコードを手に入れるには lua_getstack を呼び出すか、フックの引数として与えられる値を使います (参照: lua_Hook)。

関数に関する情報を入手するには、関数をスタックにプッシュした上で what">" で始まる文字列とします。このとき lua_getinfo によってスタックから値が一つポップされます。例えば関数 f が定義された行を知りたい場合には次のように書けます:

lua_Debug ar;
lua_getglobal(L, "f");  /* グローバル変数 'f' をスタックに積む */
lua_getinfo(L, ">S", &ar);
printf("%d\n", ar.linedefined);

文字列 what に含まれる文字が ar のどのフィールドを埋めるか、そしてスタックにどの値をプッシュするかを選択します:

what に無効なオプションが含まれると、この関数は 0 を返します。ただしその後に続く有効なオプションは通常通り処理されます。

lua_getlocal

[-0, +(0|1), -]
const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);

与えられたアクティベーションレコードあるいは関数の、ローカル変数および一時的な値に関する情報を取得します。

アクティベーションレコードを使う場合には、lua_getstack の返り値あるいはフックの引数として取得された有効なアクティベーションレコードを ar として呼び出します。調べるローカル変数はインデックス n で指定します。変数のインデックスと名前については debug.getlocal を参照してください。

lua_getlocal は変数の値をスタックにプッシュし、名前を返します。

関数を使う場合には、arNULL とした上で調べる関数をスタックトップに配置しておく必要があります。この場合に見えるのは Lua 関数のパラメータだけであり、値はスタックにプッシュされません (アクティブな変数についての情報が存在しないからです)。

インデックス n がアクティブなローカル変数の数より大きい場合には何もプッシュせずに NULL を返します。

lua_getstack

[-0, +0, -]
int lua_getstack (lua_State *L, int level, lua_Debug *ar);

インタープリタランタイムのスタックに関する情報を取得します。

この関数は指定されたレベルで実行される関数のアクティベーションレコードを特定するための情報に関する lua_Debug のフィールドを埋めます。現在実行している関数がレベル 0 で、レベル n を呼んだ関数がレベル n + 1 となります (ただし末尾呼び出しはスタックを使わないので、途中に末尾呼び出しがあるとこの規則は成り立ちません)。スタックの深さよりも大きいレベルを指定すると、lua_getstack は 0 を返します。それ以外のときは 1 を返します。

lua_getupvalue

[-0, +(0|1), -]
const char *lua_getupvalue (lua_State *L, int funcindex, int n);

スタックのインデックス funcindex にあるクロージャが持つ n 個目のアップバリューに関する情報を取得します。アップバリューの値をスタックにプッシュし、その名前を返します。n がアップバリューの個数よりも大きい場合には NULL を返します (そして何もプッシュしません)。

アップバリューについて詳しくは debug.getupvalue を参照してください。

lua_Hook

typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);

デバッグ用フック関数の型です。

フックが呼ばれるとき、引数 arevent フィールドはフックを引き起こしたイベントに設定されます。Lua はイベントを表すのに次の定数を使います:

ラインイベントでは currentline フィールドも設定されます。これら以外の ar のフィールドを取得するには、フックから lua_getinfo を呼び出す必要があります。

コールイベントでは、通常の呼び出しを表す LUA_HOOKCALL もしくは末尾呼び出しを表す LUA_HOOKTAILCALL のいずれが event となります。末尾呼び出しに対応するリターンイベントは起こりません。

Lua がフックを実行している間、他のフックの呼び出しは無効化されます。そのためフックから Lua の関数やチャンクをさらに呼ぶと、その実行はフックを呼び出さずに行われます。

フック関数は継続を持つことができません。つまり lua_yieldk, lua_pcallk, lua_callkNULL でない k を指定して呼ぶことはできません。

フック関数は次の条件が満たされるときに限って yield できます:

  1. カウントイベントとラインイベントだけが yield できる。
  2. フック関数は lua_yield の呼び出しで実行を終えなければならず、そのとき nresults は 0 でなければならない (つまり値を返してはならない)。

lua_setcstacklimit

[-0, +0, -]
int (lua_setcstacklimit) (lua_State *L, unsigned int limit);

C スタックの上限を設定します。この上限は Lua においてネストされた呼び出しがどれだけ深くなれるかを制御するので、値を大きくすればスタックオーバーフローを回避できます。成功すれば古い上限を返し、エラーがあれば 0 を返します。この関数について詳しくは標準ライブラリの同じ関数 debug.setcstacklimit を参照してください。

lua_sethook

[-0, +0, -]
void lua_sethook (lua_State *L, lua_Hook f, int mask, int count);

デバッグ用フック関数を設定します。

引数 f がフック関数を、mask がフックを呼び出すイベントを指定します。mask は次の定数をビットごとの OR で組み合わせた値です:

引数 countmaskLUA_MASKCOUNT のときに限って意味を持ちます。どのフックがどのイベントで呼ばれるのかを示します:

mask を 0 にすればフックが無効化されます。

lua_setlocal

[-(0|1), +0, -]
const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);

指定されたアクティベーションレコードのローカル変数の値を設定します。スタックトップにある値をローカル変数に代入し、その名前を返します。スタックトップにある値はポップされます。

インデックスがアクティブなローカル変数の数よりも大きいときは NULL を返します (そして何もポップしません)。

パラメータ arn の意味は lua_getlocal と同様です。

lua_setupvalue

[-(0|1), +0, -]
const char *lua_setupvalue (lua_State *L, int funcindex, int n);

クロージャのアップバリューの値を設定します。スタックトップにある値をアップバリューに代入し、その名前を返します。スタックトップにある値はポップされます。

インデックスがアップバリューの数よりも大きいときは NULL を返します (そして何もポップしません)。

パラメータ funcindexn の意味は lua_getupvalue と同様です。

lua_upvalueid

[-0, +0, -]
void *lua_upvalueid (lua_State *L, int funcindex, int n);

クロージャが持つ n 番目のアップバリューのユニークな識別子を返します。

ユニークな識別子を使うと、異なるクロージャがアップバリューを共有しているかどうかを確認できます。複数の Lua のクロージャがアップバリューを共有する (同じ外部ローカル変数にアクセスできる) とき、そのアップバリューを指すインデックスは同じ識別子を返します。

パラメータ funcindexn の意味は lua_getupvalue と同様です。ただし n はアップバリューの数より大きくてはいけません。

lua_upvaluejoin

[-0, +0, -]
void lua_upvaluejoin (lua_State *L,
                      int funcindex1, int n1,
                      int funcindex2, int n2);

インデックス funcindex1 のクロージャが持つ n1 番目のアップバリューの参照先を、インデックス funcindex2 のクロージャが持つ n2 番目のアップバリューとします。


  1. 訳注: アクティベーションレコードはスタックフレームの別名。C のスタックフレームと区別するためにこう呼んでいるのだと思われる。[return]

  2. 訳注: 例えば C で定義された関数では source"=[C]" となる。[return]

  3. 訳注: レベルは lua_getstack の引数で指定する。関数を lua_getinfo に直接渡した場合にはその関数がスタックにプッシュされる。[return]