cocos 2 dxにおけるC++とluaのインタラクション
6338 ワード
最近、書き込み熱更新モジュールでは、C++呼び出しCRUL multiインタフェースがマルチスレッドダウンロード機能を実現し、lua呼び出しにリアルタイムのステータスクエリーインタフェースを提供することを目的としており、生産者消費者モデルを採用している.TOluaを使用してluaインタフェースを手動でエクスポートするときにいくつかの問題が発生し、ここに記録されます.
luaとC++のインタラクションはluaのregistryテーブルを使用し、C/C++コードは自由に使用できるが、Luaコードは彼にアクセスできない.luaに登録するデータごとにregistryにメタテーブルを作成する.タイプ名はkey、メタテーブルはvalueである.
luaL_新metatable関数は、新しいテーブル(metatableとして使用される)を作成し、新しいテーブルをスタックの上部に配置し、テーブルとregistryのタイプ名の関連付けを確立します.この関連付けは双方向です.タイプ名をテーブルのkeyとして使用します.同時にテーブルをタイプ名として用いるkey(このような双方向の関連は、他の2つの関数の実現効率を向上させる).
lua呼び出しプロセスは、実際にはlua呼び出しC/C++がluaに登録するエージェント関数であり、エージェント関数呼び出しに関する実際の関数戻り結果はluaスタックにあり、luaは戻り値を操作する.
tolua API
TOLUA_API void tolua_open (lua_State* L)
いくつかのtoluaのグローバルtableの作成.
TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar)
名前のmoduleがnilでない場合は処理しないmoduleを作成します.
TOLUA_API void tolua_beginmodule (lua_State* L, const char* name)
モジュールまたはクラスをスタックに入れる.
TOLUA_API void tolua_usertype (lua_State* L, const char* type)
レジストリに構築されたユーザータイプを登録します.R[type]と_R[const type]のメタテーブル.
static void mapsuper (lua_State* L, const char* name, const char* base)
nameをbaseに継承するように設定、baseのすべてのスーパークラスメソッドをnameにマッピングする(baseを含むメソッド).
static void mapinheritance (lua_State* L, const char* name, const char* base)
name継承baseの設定、name_の設定mt[tolua_ubox] = base_mt[tolua_ubox],ベースクラスのtolua_uboxはサブクラスとしてtolua_は存在しませんuboxはvalueに関連付けられたweakテーブルを作成します.
インポートの例:
テスト例:
luaとC++のインタラクションはluaのregistryテーブルを使用し、C/C++コードは自由に使用できるが、Luaコードは彼にアクセスできない.luaに登録するデータごとにregistryにメタテーブルを作成する.タイプ名はkey、メタテーブルはvalueである.
luaL_新metatable関数は、新しいテーブル(metatableとして使用される)を作成し、新しいテーブルをスタックの上部に配置し、テーブルとregistryのタイプ名の関連付けを確立します.この関連付けは双方向です.タイプ名をテーブルのkeyとして使用します.同時にテーブルをタイプ名として用いるkey(このような双方向の関連は、他の2つの関数の実現効率を向上させる).
lua呼び出しプロセスは、実際にはlua呼び出しC/C++がluaに登録するエージェント関数であり、エージェント関数呼び出しに関する実際の関数戻り結果はluaスタックにあり、luaは戻り値を操作する.
tolua API
TOLUA_API void tolua_open (lua_State* L)
いくつかのtoluaのグローバルtableの作成.
TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar)
名前のmoduleがnilでない場合は処理しないmoduleを作成します.
TOLUA_API void tolua_beginmodule (lua_State* L, const char* name)
モジュールまたはクラスをスタックに入れる.
TOLUA_API void tolua_beginmodule (lua_State* L, const char* name)
{
// module lua , module _G
// bool LuaStack::init(void) luaL_register(_state, "_G", global_functions) ,
// .
if (name) { // ... module
//---- now module[name] is a table, get it's metatable to store keys
// get module[name]
lua_pushstring(L,name); // ... module name
lua_rawget(L,-2); // ... module module[name]
// Is module[name] a class table?
lua_pushliteral(L, ".isclass");
lua_rawget(L, -2); // stack: ... module module[name] class_flag
if (lua_isnil(L, -1)) {
lua_pop(L, 1); // stack: ... module module[name]
return; // not a class table, use origin table
}
lua_pop(L, 1); // stack: ... module class_table
// get metatable
if (lua_getmetatable(L, -1)) { // ... module class_table mt
lua_remove(L, -2); // ... module mt
}
//---- by SunLightJuly, 2014.6.5
} else {
lua_pushvalue(L,LUA_GLOBALSINDEX);
}
}
TOLUA_API void tolua_usertype (lua_State* L, const char* type)
レジストリに構築されたユーザータイプを登録します.R[type]と_R[const type]のメタテーブル.
static void mapsuper (lua_State* L, const char* name, const char* base)
nameをbaseに継承するように設定、baseのすべてのスーパークラスメソッドをnameにマッピングする(baseを含むメソッド).
static void mapsuper (lua_State* L, const char* name, const char* base)
{
/* push registry.super */
// _R[tolua_super] name , nil .
lua_pushstring(L,"tolua_super");
lua_rawget(L,LUA_REGISTRYINDEX); /* stack: super */
luaL_getmetatable(L,name); /* stack: super mt */
lua_rawget(L,-2); /* stack: super table */
if (lua_isnil(L,-1))
{
/* create table */
lua_pop(L,1);
lua_newtable(L); /* stack: super table */
luaL_getmetatable(L,name); /* stack: super table mt */
lua_pushvalue(L,-2); /* stack: super table mt table */
lua_rawset(L,-4); /* stack: super table */
}
/* set base as super class */
//_R[tolua_super][name_mt]["base"] = true
lua_pushstring(L,base);
lua_pushboolean(L,1);
lua_rawset(L,-3); /* stack: super table */
/* set all super class of base as super class of name */
// _R[base_mt]
luaL_getmetatable(L,base); /* stack: super table base_mt */
lua_rawget(L,-3); /* stack: super table base_table */
// base_mt, name_mt
//lua_next() :
//1 key
//2 table key-value, key value
//3 2 0 , 0.
if (lua_istable(L,-1))
{
/* traverse base table */
lua_pushnil(L); /* first key */
while (lua_next(L,-2) != 0)
{
/* stack: ... base_table key value */
lua_pushvalue(L,-2); /* stack: ... base_table key value key */
lua_insert(L,-2); /* stack: ... base_table key key value */
// key key-value , lua_pushnil
lua_rawset(L,-5); /* stack: ... base_table key */
}
}
lua_pop(L,3); /* stack: */
}
static void mapinheritance (lua_State* L, const char* name, const char* base)
name継承baseの設定、name_の設定mt[tolua_ubox] = base_mt[tolua_ubox],ベースクラスのtolua_uboxはサブクラスとしてtolua_は存在しませんuboxはvalueに関連付けられたweakテーブルを作成します.
static void mapinheritance (lua_State* L, const char* name, const char* base)
{
/* set metatable inheritance */
luaL_getmetatable(L,name);
if (base && *base)
luaL_getmetatable(L,base);
else {
if (lua_getmetatable(L, -1)) { /* already has a mt, we don't overwrite it */
lua_pop(L, 2);
return;
};
luaL_getmetatable(L,"tolua_commonclass");
};
set_ubox(L);
lua_setmetatable(L,-2);
lua_pop(L,1);
}
インポートの例:
tolua_open(tolua_S);
// stack: ... module cc ( module _G)
//LuaStack::init(void)
//luaL_register(_state, "_G", global_functions) .
tolua_beginmodule(tolua_S,"cc");
tolua_usertype(tolua_S,"cc.HotUpdate");
// module(_G), module
tolua_cclass(tolua_S,"HotUpdate","cc.HotUpdate","cc.Ref",nullptr);
tolua_beginmodule(tolua_S,"HotUpdate");
tolua_function(tolua_S,"create", lua_cocos2dx_HotUpdate_create);
tolua_function(tolua_S,"registerScriptHandler", lua_cocos2dx_HotUpdate_registerScriptHandler);
tolua_endmodule(tolua_S);
std::string typeName = "cocos2d::HotUpdate";//typeid(so::HotUpdate).name();
g_luaType[typeName] = "cc.HotUpdate";
g_typeCast["HotUpdate"] = "cc.HotUpdate";
tolua_endmodule(tolua_S);
テスト例:
local hotUpdate = cc.HotUpdate:create("", "")
print("type(HotUpdate) = ", type(HotUpdate));
print("type(cc.HotUpdate) = ", type(cc.HotUpdate));
print("type(hotUpdate) = ", type(hotUpdate))