tolua++ と class と enum と - ご機嫌斜め

次のような tolua++ に投げるコードがあったとしましょう。(class CCC; が、別ファイル の enum をメンバに持っているところがポイント)

// test.pkg
$#include "test2.h"

enum A
{
	AAA,
	BBB,
	CCC,
};

class CCC
{
public:
  A a;
  B b;
};
// test2.h
enum B
{
  B_AA,
  B_BB,
  B_CC,
};

"test.pkg" を tolua++ に投げてコード生成するとこんな感じなコードをはいてくれました。(とりあえずsetterを抜粋)

/* set function: a of class  CCC */
#ifndef TOLUA_DISABLE_tolua_set_CCC_a
static int tolua_set_CCC_a(lua_State* tolua_S)
{
  CCC* self = (CCC*)  tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
  tolua_Error tolua_err;
  if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'a'",NULL);
  if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
   tolua_error(tolua_S,"#vinvalid type in variable assignment.",&tolua_err);
#endif
  self->a = ((A) (int)  tolua_tonumber(tolua_S,2,0))
;
 return 0;
}
#endif //#ifndef TOLUA_DISABLE

/* set function: b of class  CCC */
#ifndef TOLUA_DISABLE_tolua_set_CCC_b
static int tolua_set_CCC_b(lua_State* tolua_S)
{
  CCC* self = (CCC*)  tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
  tolua_Error tolua_err;
  if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'b'",NULL);
  if ((tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"B",0,&tolua_err)))
   tolua_error(tolua_S,"#vinvalid type in variable assignment.",&tolua_err);
#endif
  self->b = *((B*)  tolua_tousertype(tolua_S,2,0))
;
 return 0;
}
#endif //#ifndef TOLUA_DISABLE

メンバ a については "列挙値 はただの int 型なんだから、キャストしてやりゃいいよね" ってコードにも関わらず、メンバ b については nullチェックとか isusertype として型チェック行われてる……ってお前さん、型 "B" を enum じゃなくてclass とか struct とかそっち方面の型として認識してるべおめー!

…って、そりゃそうですよね。 ファイル外部の型なんて自動的にゃー見てくれない以上は、そういう扱いになるのは仕方ない。「$#include "hogehoge.h"」は見えるわけないし。



というわけで、こういう時は 「$#include "test2.h"」 なんて書かずに

$pfile "test2.pkg"
$hfile "test2.h" // もしくは $#include "test2.h"

または

$ifile "test2.h"

と書くと、B も enum 型として認識してくれ、ただの int のキャストをするようなコードをはいてくれました。 よかったよかった………とは微妙にいかず…(苦笑

登録がカブるんですけどぉ!

tolua を利用する際は、 tolua_hogehoge_open 関数で型情報なりを登録しますがー、上記のコードでグルーコードを生成したらこんな登録関数をはいてくれました。

/* Open function */
TOLUA_API int tolua_test_open (lua_State* tolua_S)
{
 tolua_open(tolua_S);
 tolua_reg_types(tolua_S);
 tolua_module(tolua_S,NULL,0);
 tolua_beginmodule(tolua_S,NULL);
  tolua_constant(tolua_S,"B_AA",B_AA);
  tolua_constant(tolua_S,"B_BB",B_BB);
  tolua_constant(tolua_S,"B_CC",B_CC);
  tolua_constant(tolua_S,"AAA",AAA);
  tolua_constant(tolua_S,"BBB",BBB);
  tolua_constant(tolua_S,"CCC",CCC);
  tolua_cclass(tolua_S,"CCC","CCC","",NULL);
  tolua_beginmodule(tolua_S,"CCC");
   tolua_variable(tolua_S,"a",tolua_get_CCC_a,tolua_set_CCC_a);
   tolua_variable(tolua_S,"b",tolua_get_CCC_b,tolua_set_CCC_b);
  tolua_endmodule(tolua_S);
 tolua_endmodule(tolua_S);
 return 1;
}

B::B_AA〜B_CC の定義が生成されてる… つまり、$pfile "test2.pkg" したファイル毎にこんなコード吐くってことだべー…? こりゃちょっと無駄が多い気がする…。(実害は無いんだろうけど…)

# ちなみに、$hfile / $cfile だと、"B" がやっぱり enum として認識されなかったです


enum を認識させつつも、グルーコード吐かないってこと出来ないんっすかねもしかして…。




…というか、h ファイルごとにグルーコード吐こうとしてるのが間違ってるもしや? 一つに纏めてから吐けとかそういう話な気もしてきたぞぉ…うむむーん。