?stdfrom3http.mp3 这是空间里歌的地址连接,求歌名

http://radio./vdj5.mp3?stdfrom3http.mp3 有歌曲连接地址求歌名_百度知道version: Cocos2d-x v3.3 and higher
Call custom c++ from Lua
Cocos2d-x lua binds c++ classes, class functions, enums and some global functions to lua by using the bindings-generator (tools/bindings-generator) and by manual bindings. This allows you to call custom c++ from lua conveniently.
Call the class member function
Open lua-empty-test/src/hello.lua and you will see many function calls like cc.***. They are actually calling the class member functions. This is the initGLView function:
local function initGLView()
local director = cc.Director:getInstance()
local glView = director:getOpenGLView()
if nil == glView then
glView = cc.GLViewImpl:create(&Lua Empty Test&)
director:setOpenGLView(glView)
director:setOpenGLView(glView)
glView:setDesignResolutionSize(480, 320, cc.ResolutionPolicy.NO_BORDER)
director:setDisplayStats(true)
director:setAnimationInterval(1.0 / 60)
The relationship between lua function call and the c++ function call as follow:
cc.Director:getInstance()
cocos2d::Director::getInstance()
director:getOpenGLView()
director-&getOpenGLView
cc.GLViewImpl:create(&Lua Empty Test&)
cocos2d::GLViewImpl::create(&Lua Empty Test&)
glView:setDesignResolutionSize(480, 320, cc.ResolutionPolicy.NO_BORDER)
glview-&glView:setDesignResolutionSize(480, 320, ResolutionPolicy::NO_BORDER)
From this table, we can see that the functions called in lua are very similar with the functions called in c++. These are some key points that we need to pay attention to:
cc is a module name like namespace name in c++,it is cocos2d-x 3.0 new features. The relation between lua modules and c++ namespaces is as follow:
Lua module name
c++ namespace
cocos2d, cocos2d::extension, CocosDenshion, cocosbuilder
cocos2d::ui
cocostudio, cocostudio::timeline
cocos2d::experimental, cocos2d::experimental::ui
static and non-static c++ functions are called in lua using :
cc.ResolutionPolicy.NO_BORDER corresponds to ResolutionPolicy::NO_BORDER which is enum value in the c++. enum values are bound to lua by manual.
Different modules use different lua files to keep the bindings value:
moudle name
const value files
Cocos2dConstants.lua, ExtensionConstants.lua, NetworkConstants.lua
GuiConstants.lua
StudioConstants.lua
experimentalUIConstants.lua
For some functions, their parameters include cocos2d::Vec2, cocos2d::Vec3 we should do a conversion to call c++ function.For example:
void Node::setPosition(const Vec2& position)
In c++, we should call this function like this:
nodeObj-&setPosition(Vec2(0.0f, 0.0f))
In lua, we should call the function like this:
nodeObj:setPosition(cc.p(0.0, 0.0))
cc.p(0.0, 0.0) is to construct an anonymous table like this {x = 0, y =0}
The other parametric types that should be converted are:
parametric types
lua conversional format
cocos2d::Point
{x = numValue, y = numValue}
cocos2d::Vec3
{x = numValue, y = numValue, z = numValue}
cocos2d::Vec4
{x = numValue, y = numValue, z = numValue, w = numValue}
cocos2d::Rect
{x = numValue, y = numValue, width = numValue, height = numValue}
cocos2d::Size
{width = numValue, height = numValue}
cocos2d::Color4B
{r = numValue, g = numValue, b = numValue, a = numValue}
cocos2d::Color4F
{r = numValue, g = numValue, b = numValue, a = numValue}
cocos2d::Color3B
{r = numValue, g = numValue, b = numValue}
cocos2d::PhysicsMaterial
{density = numValue, restitution = numValue, friction = numValue}
cocos2d::AffineTransform
{a = numValue, b = numValue, c = numValue, d = numValue, tx = numValue, ty = numValue}
cocos2d::FontDefinition
{fontName = stringValue, fontSize = numValue, fontAlignmentH = numValue, fontAlignmentV = numValue, fontFillColor = {r = numValue, g = numValue, b = numValue}, fontDimensions = {width = numValue, height = numValue}, shadowEnabled = boolValue[,shadowOffset = {width = numValue, height = numValue}, shadowBlur = numValue, shadowOpacity = numValue], strokeEnabled = boolValue[,strokeColor
{r = numValue, g = numValue, b = numValue}, strokeSize = numValue]}
cocos2d::Vector
{objValue1,objValue2,...,objValuen,...}
cocos2d::Map&std::string, T&
{key1 = objValue1, key2 = objValue2,..., keyn = objValuen,...}
cocos2d::Value
{objValue1,objValue2,...,objValuen,...} or key1 = objValue1, key2 = objValue2,..., keyn = objValuen,...} or stringValue or boolValue or numValue
cocos2d::ValueMap
{key1 = Value1, key2 = Value2,..., keyn = Valuen,...}
cocos2d::ValueMapIntKey
{numKey1 = Value1, intKey2 = Value2, ...,intKeyn = Valuen,...}
cocos2d::ValueVector
{Value1, Value2, ..., Valuen, ...}
std::vector&string&
{stringValue1, stringValue2, ..., stringValuen, ...}
std::vector&int&
{numValue1, numValue2, ..., numValuen, ...}
std::vector&float&
{numValue1, numValue2, ..., numValuen, ...}
std::vector&unsigned short&
{numValue1, numValue2, ..., numValuen, ...}
cocos2d::Mat4
{numValue1,numValue2,..., numValue16}
cocos2d::TTFConfig
{fontFilePath = stringValue, fontSize = numValue, glyphs = numValue, customGlyphs = stringValue, distanceFieldEnabled = boolValue, outlineSize = numValue}
cocos2d::MeshVertexAttrib
{size = numValue, type = numValue, vertexAttrib = numValue, vertexAttrib =numValue}
cocos2d::BlendFunc
{ src = numValue, dst = numValue}
Call global functions
cocos2d-x v3 also binds some global functions to lua manually, such as kmGLPushMatrix, kmGLTranslatef and kmGLLoadMatrix. We can call these global functions in lua as follows:
kmGLPopMatrix()
Call OpenGL functions
cocos2d-x v3 binds some OpenGL functions to lua. All the OpenGL functions are in the gl module and can be called as follows:
local glNode
= gl.glNodeCreate()
glNode:setContentSize(cc.size(256, 256))
glNode:setAnchorPoint(cc.p(0.5, 0.5))
uniformCenter = gl.getUniformLocation(program,&center&)
uniformResolution
= gl.getUniformLocation( program, &resolution&)
You can refer to lua-tests/DrawPrimitiveTest and lua-tests/OpenGLTest for more information.
Bind a c++ class to lua by bindings-generator automatically
Since cocos2d-x v3.0, there is a tools called
to bind c++ class to lua automatically.
The bindings-generator is based on tolua++. There is an ini file in the tools/tolua directory and then run the genbindings.py script to generate the binding code.
Create a custom class
Consider this code:
#ifndef __CUSTOM__CLASS
#define __CUSTOM__CLASS
#include &cocos2d.h&
namespace cocos2d {
class CustomClass : public cocos2d::Ref
CustomClass();
~CustomClass();
static cocos2d::CustomClass* create();
bool init();
CREATE_FUNC(CustomClass);
the cpp file was omitted
because the bindings-generator only scan the header files
The custom class should be inherited from the Ref class, this is mainly due to the destructor of Ref calling removeScriptObjectByObject to reduce the reference count of userdata which gets created in the c++ automatically to avoid memory leak.
Add a new cocos2dx_custom.ini file
In tools/lua folder create a new file named cocos2dx_custom.ini as:
[cocos2dx_custom]
# the prefix to be added to the generated functions. You might or might
not use this in your own
# templates
prefix = cocos2dx_custom
# create a target namespace (in javascript, this would create some code
like the equiv. to `ns = ns
# all classes will be embedded in that namespace
target_namespace = cc
android_headers =
-I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/include
android_flags = -D_SIZE_T_DEFINED_
clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include
clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__
cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/my -I%(cocosdir)s/cocos/2d -I%(cocosdir)s/cocos/base -I%(cocosdir)s/cocos/ui -I%(cocosdir)s/cocos/physics -I%(cocosdir)s/cocos/2d/platform -I%(cocosdir)s/cocos/2d/platform/android -I%(cocosdir)s/cocos/math/kazmath -I%(cocosdir)s/extensions -I%(cocosdir)s/external -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s
cocos_flags = -DANDROID -DCOCOS2D_JAVASCRIPT
cxxgenerator_headers =
# extra arguments for clang
extra_arguments =
%(android_headers)s %(clang_headers)s %(cxxgenerator_headers)s %(cocos_headers)s %(android_flags)s %(clang_flags)s %(cocos_flags)s %(extra_flags)s
# what headers to parse
headers = %(cocosdir)s/cocos/my/CustomClass.h
# what classes to produce code for. You can use regular expressions here.
# When testing the regular expression, it will be enclosed in &^$&, like
# this: &^Menu*$&.
classes = CustomClass.*
# what should we skip? in the format ClassName::[function function]
# ClassName is a regular expression, but will be used like this:
# &^ClassName$& functions are also regular expressions, they will not be
# surrounded by &^$&. If you want to skip a whole class, just add a single
# &*& as functions. See bellow for several examples. A special class name
# is &*&, which will apply to all class names. This is a convenience
# wildcard to be able to skip similar named functions from all classes.
rename_functions =
rename_classes =
# for all class names, should we remove something when registering in the
# target VM?
remove_prefix =
# classes for which there will be no &parent& lookup
classes_have_no_parents =
# base classes which will be skipped when their sub-classes found them.
base_classes_to_skip =
# classes that create no constructor
# Set is special and we will use a hand-written constructor
abstract_classes =
# Determining whether to use script object(js object) to control the
# lifecycle of native(cpp) object or the other way around. Supported
# values are 'yes' or 'no'.
script_control_cpp = no
All of the config files under tools/tolua use the same format. Here is a list which you should consult when writing your own ini file:
[title]: To config the title which will by used by the tools/tolua/gengindings.py scripts. Generally, the title could be the file name.
prefix: To config the prefix of a function name, generally, we also use the file name as the prefix.
target_namespace: To config the module name in lua. Here we use the cc as the module name, when you want to use CustomClass in lua, you must put a prefix named cc in front of the name. For example, the CustomClass could be reference as cc.CustomClass.
headers: To config all the header files needed for parsing and the %(cocosdir)s is the engine root path of cocos2d-x.
classes: To config all the classes needed to bind. Here it supports regular expression. So we could set MyCustomClass.* here. For looking more specified usage, you could ref to tools/tolua/cocos2dx.ini.
skip: To config the functions needed to be omit. Now the bindings-generator can't parse void* type and also the delegate type, so these types needed to be bind manually. And at this circumstance, you should omit all these types first and then to bind them manually. You could ref to the config files under path cocos/scripting/lua-bindings/auto .
rename_functions: To config the functions need to be renamed in the scripting layer. Due to some reasons, developers want more scripting friendly API, so the config option is for this purpose.
rename_classes: Not used any more.
remove_prefix: Not used any more.
classes_have_no_parents: To config
the parent class needed to be filter. This option is seldom modified.
abstract_classes: To config the classes whose public constructor don't need to be exported.
script_control_cpp:yes.
To config whether the scripting layer manage the object life time or not. If no, then the c++ layer cares about their life time. Now, it is imperfect to control native object's life time in scripting layer. So you could simply leave it to no.
Subclassing
Sometimes we want to add some new functions to extend the bindings, think inheritance in c++. Through class(classname, super) function in the cocos/scripting/lua-bindings/script/cocos2d/extern.lua, we can realize this requirement easily. The details function are as follow:
function class(classname, super)
local superType = type(super)
if superType ~= &function& and superType ~= &table& then
superType = nil
super = nil
if superType == &function& or (super and super.__ctype == 1) then
if superType == &table& then
for k,v in pairs(super) do cls[k] = v end
cls.__create = super.__create
cls.__create = super
= function() end
cls.__cname = classname
cls.__ctype = 1
function cls.new(...)
local instance = cls.__create(...)
for k,v in pairs(cls) do instance[k] = v end
instance.class = cls
instance:ctor(...)
return instance
if super then
cls = clone(super)
cls.super = super
cls = {ctor = function() end}
cls.__cname = classname
cls.__ctype = 2
cls.__index = cls
function cls.new(...)
local instance = setmetatable({}, cls)
instance.class = cls
instance:ctor(...)
return instance
return cls
Through this function, we can see inheritance easily. Example, if we want to derive from cc.Node:
Define a subclass by class function
local SubNode = class(&SubNode&,function()
return cc.Node:create()
function SubNode:ctor()
function SubNode:addSprite(filePath)
local sprite = cc.Sprite:create(filePath)
sprite:setPosition(cc.p(0, 0))
self:addChild(sprite)
Create a object of subclass and use it:
local node = SubNode.new()
node:addSprite( &xxx.jpg& )
Note: new is implemented by default in the class function. Since the type of the second parameter is function, when we call new, this is what happens:
function SubNode.new(...)
local instance = cc.Node:create()
for k,v in pairs(SubNode) do instance[k] = v end
instance.class = SubNode
instance:ctor(...)
return instance
The object created by new have all the properties and behaviors of the cc.Node object. It also has the properties of the SubNode as it is derived from cc.Node:
function SubNode:setPostion(x,y)
print(string.format(&x = %0.2f, y = %0.2f&), x, y)
If we still need to call the function of the same name of super class:
getmetatable(SubNode):setPosition(x, y)
The override functions of inherited class in lua can't be called in the c++.
Memory Management
Cocos2d-x v3.x uses the memory management and garbage collection of lua itself except the release of userdata. If the corresponding classes are derived from Ref the release of userdata is managed in c++ by the register table named
toluafix_refid_ptr_mapping and tolua_value_root.
Simple Test Case
Create a Sprite in the head of createDog function
local testSprite = cc.Sprite:create(&res/land.png&)
Then call the Sprite in the tick function as follow:
testSprite:getPosition()
After a period of time, we will see the error message as follows:
cocos2d: [LUA-print] stack traceback:
[string "src/hello.lua"]:13: in function
[C]: in function 'getPosition'
[string "src/hello.lua"]:98: in function
cocos2d: [LUA-print] ----------------------------------------
cocos2d: [LUA-print] ----------------------------------------
cocos2d: [LUA-print] LUA ERROR: [string "src/hello.lua"]:98: invalid 'self' in function 'tolua_cocos2d_Node_getPosition'
This error is triggered because the testsprite didn't add any other node as a child after creation. The corresponding c++ object was released at the end of the frame.
Memory Management for Class Object
The Class Members of Ref Class for Memory Management
In CCRef.h we see the usage of CC_ENABLE_SCRIPT_BINDING:
#if CC_ENABLE_SCRIPT_BINDING
unsigned int
void* _scriptO
Notice _ID and _luaID, are very important when you push a Ref object to lua by calling toluafix_pushusertype_ccobject to store a key-value table named toluafix_refid_ptr_mapping in the registry. The _ID is key and the related c++ object pointer is value. The related code fragment in the toluafix_pushusertype_ccobject is:
lua_pushstring(L, TOLUA_REFID_PTR_MAPPING);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushinteger(L, refid);
lua_pushlightuserdata(L, vPtr);
lua_rawset(L, -3);
lua_pop(L, 1);
TOLUA_REFID_PTR_MAPPING is macro definition represent for &toluafix_refid_ptr_mapping&
LUA_REGISTRYINDEX is definition of Pseudo-Index for registry of Lua
refid is value of _ID
vPtr is value of related c++ object pointer
Create a Ref object from Lua
Call the cocos2d::Sprite::create(&res/land.png&) by lua bindings to create a Sprite object and push it into lua stack:
std::string arg0;
ok &= luaval_to_std_string(tolua_S, 2,&arg0, &cc.Sprite:create&);
if (!ok) { break; }
cocos2d::Sprite* ret = cocos2d::Sprite::create(arg0);
object_to_luaval&cocos2d::Sprite&(tolua_S, &cc.Sprite&,(cocos2d::Sprite*)ret);
Call toluafix_pushusertype_ccobject when push created object to lua stack
if (std::is_base_of&cocos2d::Ref, T&::value)
cocos2d::Ref* dynObject = (cocos2d::Ref*)(ret);
int ID = (int)(dynObject-&_ID) ;
int* luaID = &(dynObject-&_luaID);
toluafix_pushusertype_ccobject(L,ID, luaID, (void*)ret,type);
In the toluafix_pushusertype_ccobject , we will use two tables named &toluafix_refid_ptr_mapping& and &toluafix_refid_type_mapping& in lua's registry to store the two key-value pairs about _ID-object pointer and _ID-object type name.The details are as follow:
if (*p_refid == 0)
*p_refid =
lua_pushstring(L, TOLUA_REFID_PTR_MAPPING);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushinteger(L, refid);
lua_pushlightuserdata(L, vPtr);
lua_rawset(L, -3);
lua_pop(L, 1);
lua_pushstring(L, TOLUA_REFID_TYPE_MAPPING);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushinteger(L, refid);
lua_pushstring(L, vType);
lua_rawset(L, -3);
lua_pop(L, 1);
Call tolua_pushusertype_internal to determine whether to create a new userdata, or just update the userdata.
void tolua_pushusertype_internal (lua_State* L, void* value, const char* type, int addToRoot)
if (value == NULL)
lua_pushnil(L);
luaL_getmetatable(L, type);
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
lua_pushstring(L,&tolua_ubox&);
lua_rawget(L,-2);
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
lua_pushstring(L, &tolua_ubox&);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushlightuserdata(L,value);
lua_rawget(L,-2);
if (lua_isnil(L,-1))
lua_pop(L,1);
lua_pushlightuserdata(L,value);
*(void**)lua_newuserdata(L,sizeof(void *)) =
lua_pushvalue(L,-1);
lua_insert(L,-4);
lua_rawset(L,-3);
lua_pop(L,1);
lua_pushvalue(L, -2);
lua_setmetatable(L,-2);
#ifdef LUA_VERSION_NUM
lua_pushvalue(L, TOLUA_NOPEER);
lua_setfenv(L, -2);
lua_insert(L,-2);
lua_pop(L,1);
lua_pushstring(L,&tolua_super&);
lua_rawget(L,LUA_REGISTRYINDEX);
lua_getmetatable(L,-2);
lua_rawget(L,-2);
if (lua_istable(L,-1))
lua_pushstring(L,type);
lua_rawget(L,-2);
if (lua_toboolean(L,-1) == 1)
lua_pop(L,3);
lua_remove(L, -2);
lua_pushvalue(L, -5);
lua_setmetatable(L,-5);
lua_pop(L,3);
lua_remove(L, -2);
if (0 != addToRoot)
lua_pushvalue(L, -1);
tolua_add_value_to_root(L, value);
We use a table named ubox to store key-value pairs about userdata and object pointer. This table would be used in the destruction of the object.
Call tolua_add_value_to_root to add a reference count for userdata in lua by the tolua_value_root table in lua registry. The mechanism will make the object in lua wouldn't collected by lua gc. Example:
local node = cc.Node:create()
node.extendValue = 10000
nodeParent:addChild(node, 0 , 9999)
This code creates a node object and extends the attributes of the node object dynamically by lua's feature. When we want to get this node and its extended attribute somewhere, we can do as follows:
local child = lnodeParent:getChildByTag(9999)
print(child.extendValue)
If we don't call the tolua_add_value_to_root, the result of print(child.extendValue) would be uncertain. Sometimes the result would be 10000 and sometimes it would be nil. This is because we wouldn't control lua's automatic gc effectively. When lua gc thinks there are no other references for this userdata it will collect this userdata. When we call getChildByTag to get a node object, it would create a new userdata and the extended attributes would disapper. We add a reference count for the userdata tolua_value_root table in lua registry in the c++ to avoid generating this error.
The Release of the Userdata
When calling the desturctor of Ref, it will trigger the release of the userdata.
In the destructor of Ref, we can see:
#if CC_ENABLE_SCRIPT_BINDING
if (_luaID)
ScriptEngineManager::getInstance()-&getScriptEngine()-&removeScriptObjectByObject(this);
After we push a c++ object to lua, the related _luaID would be not 0. We now can call removeScriptObjectByObject
The removeScriptObjectByObject called would trigger the call of toluafix_remove_ccobject_by_refid, and this function would call some lua c APIs to operate the table like toluafix_refid_ptr_mapping, toluafix_refid_type_mapping and tolua_value_root table in the registry.
The specific implementation of toluafix_remove_ccobject_by_refid is as follows:
TOLUA_API int toluafix_remove_ccobject_by_refid(lua_State* L, int refid)
void* ptr = NULL;
const char* type = NULL;
void** ud = NULL;
if (refid == 0) return -1;
lua_pushstring(L, TOLUA_REFID_PTR_MAPPING);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushinteger(L, refid);
lua_rawget(L, -2);
ptr = lua_touserdata(L, -1);
lua_pop(L, 1);
if (ptr == NULL)
lua_pop(L, 1);
return -2;
lua_pushinteger(L, refid);
lua_pushnil(L);
lua_rawset(L, -3);
lua_pop(L, 1);
lua_pushstring(L, TOLUA_REFID_TYPE_MAPPING);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushinteger(L, refid);
lua_rawget(L, -2);
if (lua_isnil(L, -1))
lua_pop(L, 2);
printf(&[LUA ERROR] remove CCObject with NULL type, refid: %d, ptr: %p\n&, refid, ptr);
return -1;
type = lua_tostring(L, -1);
lua_pop(L, 1);
lua_pushinteger(L, refid);
lua_pushnil(L);
lua_rawset(L, -3);
lua_pop(L, 1);
luaL_getmetatable(L, type);
lua_pushstring(L, &tolua_ubox&);
lua_rawget(L, -2);
if (lua_isnil(L, -1))
lua_pop(L, 1);
lua_pushstring(L, &tolua_ubox&);
lua_rawget(L, LUA_REGISTRYINDEX);
tolua_remove_value_from_root(L, ptr);
lua_pushlightuserdata(L, ptr);
lua_rawget(L,-2);
if (lua_isnil(L, -1))
lua_pop(L, 3);
return -3;
lua_pushvalue(L, LUA_REGISTRYINDEX);
lua_setfenv(L, -2);
ud = (void**)lua_touserdata(L, -1);
lua_pop(L, 1);
if (ud == NULL)
printf(&[LUA ERROR] remove CCObject with NULL userdata, refid: %d, ptr: %p, type: %s\n&, refid, ptr, type);
lua_pop(L, 2);
return -1;
*ud = NULL;
lua_pushlightuserdata(L, ptr);
lua_pushnil(L);
lua_rawset(L, -3);
lua_pop(L, 2);
The steps are as follows:
Get related object pointer stored in the toluafix_refid_ptr_mapping table by the value of _luaID. Store it.
Remove reference relationship of the object pointer from toluafix_refid_ptr_mapping table by _luID
Get related type name stored in the tolua_refid_type_mapping table by the value of _luaID,then store it
Remove reference relationship of type name from tolua_refid_type_mapping table by _luID
Get the related metatable by the type name
Get the ubox table
Remove reference relationship of userdata from tolua_value_root table by the object pointer got in the upper step
Clean userdata and remove reference relationship of uesrdata from ubox by the object pointer got in the upper step.Note:To destroy a object cited by lua, we only called '*ud = NULL;'
Through the above steps,the refernce relationships in the toluafix_refid_ptr_mapping、tolua_refid_type_mapping and tolua_refid_type_mapping table in the registry would be removed, release the userdata which is created when push c++ object to lua stack, and when lua gc trigger, the related object would be collected if there is no other place refer
Memory Management for Lua Callback Function
Cocos2dx have been used toluafix_refid_function_mapping table in the registry to manage the gc of lua callback function
Add a reference for Lua Callback Function
When we define a lua function which would be called throuch c++ codes, we whould store the pointer of this function in the toluafix_refid_function_mapping table by calling toluafix_ref_function function in the tolua_fix.cpp.Cocos2d-x bound
a series of functions like registerScriptHandler and addEventListener to finish this work.
Let's use registerScriptHandler of Node as a sample,we could use it as follows in lua:
local function onNodeEvent(event)
if &enter& == event then
nodeObject:registerScriptHandler(onNodeEvent)
The related bindings function is named tolua_cocos2d_Node_registerScriptHandler in the lua_cocos2dx_manual.cpp,the most important sections are as follows:
LUA_FUNCTION handler = toluafix_ref_function(tolua_S,2,0);
ScriptHandlerMgr::getInstance()-&addObjectHandler((void*)self, handler, ScriptHandlerMgr::HandlerType::NODE);
toluafix_ref_function is implemented to store the related function pointer into toluafix_refid_function_mapping table in the registry with a static variable named s_function_ref_id.This operation makes lua function avoid being collected by lua gc because that toluafix_refid_function_mapping table have a reference of this function. The details are as follow:
TOLUA_API int toluafix_ref_function(lua_State* L, int lo, int def)
if (!lua_isfunction(L, lo)) return 0;
s_function_ref_id++;
lua_pushstring(L, TOLUA_REFID_FUNCTION_MAPPING);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushinteger(L, s_function_ref_id);
lua_pushvalue(L, lo);
lua_rawset(L, -3);
lua_pop(L, 1);
return s_function_ref_
addObjectHandler is used to stored the map of object pointer and pair of s_function_ref_id and handler type.
Remove a reference for Lua Callback Function
If lua callback function become useless, we should remove the reference in the toluafix_refid_function_mapping table in the registry. Cocos2d-x provided the toluafix_remove_function_by_refid function to realize it. This function could be called by removeScriptHandler of LuaStack、removeScriptHandler of LuaEngine or directly. The details are as follows:
TOLUA_API void toluafix_remove_function_by_refid(lua_State* L, int refid)
lua_pushstring(L, TOLUA_REFID_FUNCTION_MAPPING);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushinteger(L, refid);
lua_pushnil(L);
lua_rawset(L, -3);
lua_pop(L, 1);
refid is the corresponding value of s_function_ref_id.
For Ref object,we would call ScriptHandlerMgr::getInstance()-&removeObjectAllHandlers to remove all the reference function relationship which added by the ScriptHandlerMgr::getInstance()-&addObjectHandler automatically
Because Cocos2d-x v3.x support the features of c++ 11, we can call the related remove function through the lambda function.
For example:
LUA_FUNCTION handler = (
toluafix_ref_function(tolua_S, 3, 0));
self-&addImageAsync(configFilePath, [=](Texture2D* tex){
int ID = (tex) ? (int)tex-&_ID : -1;
int* luaID = (tex) ? &tex-&_luaID :
toluafix_pushusertype_ccobject(tolua_S, ID, luaID, (void*)tex, &cc.Texture2D&);
LuaEngine::getInstance()-&getLuaStack()-&executeFunctionByHandler(handler,1);
LuaEngine::getInstance()-&removeScriptHandler(handler);
By the mechanism of the lambda, we could get the value of handler which represents the corresponding value of s_function_ref_id. When we finish calling lua callback function,we could call LuaEngine::getInstance()-&removeScriptHandler(handler) directly to remove the reference of lua callback function.
References
For advance contents, please read
for more details.
Sign up for our newsletter to keep up with the latest developments, releases and updates for Cocos2d-x.}

我要回帖

更多关于 同一首歌mp3 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信