Tolua++実装解析

60742 ワード

tolua++は、C/C++の関数とオブジェクトをLuaスクリプトにエクスポートするためのツールです.
このツールを使用するための基本的な手順は、次のとおりです.
エクスポートするC/C++関数とオブジェクト定義を書き込む.pkgファイル;
tolua++ツールを実行します.pkgファイルのコンパイルを目標とする.cppファイル;
ターゲットをcppファイルはプロジェクトに参加し、Lua仮想マシンが有効になった後、ターゲットファイルのopen()関数を呼び出してエクスポートされたコンテンツを登録します.
~
tolua++ツールで生成されたターゲットファイル
各ターゲットファイルは一連から構成する.pkgファイルをコンパイルし、主に以下の機能を完成します.
C/C++からエクスポートされるすべてのタイプ、関数、およびオブジェクトを定義します.
すべてのタイプとそのメソッドを登録します.
~
エクスポートするメソッドの定義
C関数でもC++オブジェクトの方法でも,すべて静的関数として導出される.
C関数のエクスポート形式は次のとおりです.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
static int tolua_math2dx_luabinding_dist00(lua_State* tolua_S) {  tolua_Error tolua_err;  if (!tolua_isnumber(tolua_S,1,0,&tolua_err) ||  !tolua_isnumber(tolua_S,2,0,&tolua_err) ||  !tolua_isnumber(tolua_S,3,0,&tolua_err) ||  !tolua_isnumber(tolua_S,4,0,&tolua_err) ||  !tolua_isnoobj(tolua_S,5,&tolua_err))  {  goto tolua_lerror;  }  else  {  float p1x = (float)tolua_tonumber(tolua_S,1,0);  float p1y = (float)tolua_tonumber(tolua_S,2,0);  float p2x = (float)tolua_tonumber(tolua_S,3,0);  float p2y = (float)tolua_tonumber(tolua_S,4,0);  {  float tolua_ret = dist(p1x, p1y, p2x, p2y);  tolua_pushnumber(tolua_S, tolua_ret);  }  }  return 1; tolua_lerror:  tolua_error(tolua_S,"#ferror in function 'dist'.",&tolua_err);  return 0; } 

このエクスポートモジュールの名前はmath 2 dx_なのでluabindingなので、エクスポート関数の接頭辞はtolua_です.math2dx_luabinding_ .導出関数distの名前には、存在する可能性のある関数のリロードを区別するために接尾辞00も追加されている.
関数dist 00()をエクスポートするには、次の手順に従います.
まずstackから関数のパラメータを抽出し,タイプを一つ一つ判断する.タイプが一致しない場合は、エラー情報を出力し、実行を中断します.
パラメータを一時変数にコピーし、ターゲット関数dist()を呼び出し、dist()に戻り値がある場合、結果をstackにpushします.
dist 00()は、最後にdist()関数の戻り値の個数を返す.
~
C++オブジェクトの場合,メソッドはクラス静的メソッドとインスタンスメソッドの2つに分類される.
tolua++からエクスポートされたC++クラスの静的メソッドは":"オペレータで呼び出されます.
local request = CCHttpRequest:create()

したがって、エクスポート関数に入力する最初のパラメータはCCHttpRequestモジュールです.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// CCHttpRequest:create() static int tolua_cocos2dx_extension_network_CCHttpRequest_create00(lua_State* tolua_S) {  tolua_Error tolua_err;  if (!tolua_isusertable(tolua_S,1,"CCHttpRequest",0,&tolua_err) ||  (tolua_isvaluenil(tolua_S,2,&tolua_err) ||  !toluafix_isfunction(tolua_S,2,"LUA_FUNCTION",0,&tolua_err)) ||  !tolua_isstring(tolua_S,3,0,&tolua_err) ||  !tolua_isnumber(tolua_S,4,1,&tolua_err) ||  !tolua_isnoobj(tolua_S,5,&tolua_err))  {  goto tolua_lerror;  }  else  {  LUA_FUNCTION listener = toluafix_ref_function(tolua_S,2,0);  const char* url = (const char*)tolua_tostring(tolua_S,3,0);  CCHttpRequestMethod method = (CCHttpRequestMethod)tolua_tonumber(tolua_S,  4,CCHttpRequestMethodGET);  {  CCHttpRequest* tolua_ret = CCHttpRequest::create(listener,url,method);  tolua_pushusertype(tolua_S,(void*)tolua_ret,"CCHttpRequest");  }  }  return 1; tolua_lerror:  tolua_error(tolua_S,"#ferror in function 'create'.",&tolua_err);  return 0; } 

PS:個人的にC++オブジェクトを1つのLua moduleと見なす場合、クラススタティックメソッドの呼び出し方式はCCHttpRequestであるべきである.create()は、インスタンスメソッドと区別するために使用されます.
インスタンスメソッドのエクスポートは大きく異なりません.stackの最初の値がオブジェクトインスタンスであるかどうかを確認する必要があります.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// CCHttpRequest:start() static int tolua_cocos2dx_extension_network_CCHttpRequest_start00(lua_State* tolua_S) {  tolua_Error tolua_err;  if (!tolua_isusertype(tolua_S,1,"CCHttpRequest",0,&tolua_err) ||  !tolua_isboolean(tolua_S,2,1,&tolua_err) ||  !tolua_isnoobj(tolua_S,3,&tolua_err))  {  goto tolua_lerror;  }  else  {  CCHttpRequest* self = (CCHttpRequest*)tolua_tousertype(tolua_S,1,0);  if (!self)  {  tolua_error(tolua_S,"invalid 'self' in function 'start'", NULL);  }  bool isCached = (bool)tolua_toboolean(tolua_S,2,false);  self->start(isCached);  }  return 0; tolua_lerror:  tolua_error(tolua_S,"#ferror in function 'start'.",&tolua_err);  return 0; } 

エクスポートするメソッドをすべて定義すると、tolua++ターゲットファイルはすべてのモジュールを定義し、上記のエクスポートメソッドを登録します.
~
モジュールとメソッドの登録
C関数ではLuaのグローバルネームスペースに追加され、各C++オブジェクトではクラス名と同じtableが登録され、グローバルネームスペースに追加されます.
C++オブジェクトに対応するtableを追加すると、エクスポートされたクラス静的メソッドとインスタンスメソッドがこのtableに追加されます.
~
tolua++ライブラリ
ターゲットファイルを正常に動作させるには、tolua++ライブラリが提供する機能に依存する必要があります.このライブラリには、次の機能があります.
push各種値からlua stackまで;
pushオブジェクトまたは構造をlua stackに;
lua stackから値やオブジェクトなどを取り出す.
lua stackの値のタイプを確認します.
lua値が回収されたときにオブジェクトインスタンスを削除します.
実はこの文章はまだ多くの内容があるはずですが、私は本当に書くのがおっくうです...このプログラム猿を許してください--#
次の文章が私のポイントだからです:)
~
-EOF-