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