您的位置:首页 > 移动开发 > Cocos引擎

Cocos2d-x源码啃食第一谈

2015-10-10 10:25 363 查看
第一篇博客,先鼓个掌纪念一下,啪啪啪啪。。。


正文开始。

从 CCRef.h 开始

/** Interface that defines how to clone an Ref */
class CC_DLL Clonable
{
public:
/** returns a copy of the Ref 返回一个Ref的拷贝*/
virtual Clonable* clone() const = 0;
/**
* @js NA
* @lua NA
*/
virtual ~Clonable() {};

/** returns a copy of the Ref.
@deprecated Use clone() instead
*/
CC_DEPRECATED_ATTRIBUTE Ref* copy() const
{
// use "clone" instead
CC_ASSERT(false);
return nullptr;
}
};


关于开始的 CC_DLL,f12并没有查到定义,后来到论坛,具体解释http://www.ziliao1.com/Article/Show/716662CB4AD94EB2D020C3E74EA62A4C.html

class CC_DLL Ref
{
public:
/**
* Retains the ownership.保持所有权
*
* This increases the Ref's reference count.增加计数引用
*
* @see release, autorelease
* @js NA
*/
void retain();


在cpp文件中为

void Ref::retain()
{
CCASSERT(_referenceCount > 0, "reference count should greater than 0");
++_referenceCount;
}


/**
* Release the ownership immediately.立即释放所有权
*
* This decrements the Ref's reference count.缩减计数
*
* If the reference count reaches 0 after the descrement, this Ref is
* destructed.如果释放后为0,将自毁
*
* @see retain, autorelease
* @js NA
*/
void release();


在cpp文件中为

void Ref::release()
{
CCASSERT(_referenceCount > 0, "reference count should greater than 0");
--_referenceCount;

if (_referenceCount == 0)
{
#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
auto poolManager = PoolManager::getInstance();
if (!poolManager->getCurrentPool()->isClearing() && poolManager->isObjectInPools(this))
{
// Trigger an assert if the reference count is 0 but the Ref is still in autorelease pool.
// This happens when 'autorelease/release' were not used in pairs with 'new/retain'.
//
// Wrong usage (1):
//
// auto obj = Node::create();   // Ref = 1, but it's an autorelease Ref which means it was in the autorelease pool.
// obj->autorelease();   // Wrong: If you wish to invoke autorelease several times, you should retain `obj` first.
//
// Wrong usage (2):
//
// auto obj = Node::create();
// obj->release();   // Wrong: obj is an autorelease Ref, it will be released when clearing current pool.
//
// Correct usage (1):
//
// auto obj = Node::create();
//                     |-   new Node();     // `new` is the pair of the `autorelease` of next line
//                     |-   autorelease();  // The pair of `new Node`.
//
// obj->retain();
// obj->autorelease();  // This `autorelease` is the pair of `retain` of previous line.
//
// Correct usage (2):
//
// auto obj = Node::create();
// obj->retain();
// obj->release();   // This `release` is the pair of `retain` of previous line.
CCASSERT(false, "The reference shouldn't be 0 because it is still in autorelease pool.");
}
#endif
delete this;
}
}


/**
* Release the ownership sometime soon automatically.自动释放
*
* This descrements the Ref's reference count at the end of current在流的末尾自动测量计数
* autorelease pool block.
*
* If the reference count reaches 0 after the descrement, this Ref is
* destructed.
*
* @returns The Ref itself.
*
* @see AutoreleasePool, retain, release
* @js NA
* @lua NA
*/
Ref* autorelease();
Ref* Ref::autorelease()
{
PoolManager::getInstance()->getCurrentPool()->addObject(this);//PoolManager用于‘池’管理,获取这个Ref对象后,通过<span style="font-family: Arial, Helvetica, sans-serif;">getCurrentPool加入自动释放池</span>
return this;
}

还有一个getReferenceCount函数,用于返回计数,代码就不贴了。

看看构造和析构。

首先是构造

Ref::Ref()
: _referenceCount(1) // when the Ref is created, the reference count of it is 1
{
#if CC_ENABLE_SCRIPT_BINDING
static unsigned int uObjectCount = 0;
_luaID = 0;
_ID = ++uObjectCount;
#endif
}


_ID 和_luaID

public:
/// object id, ScriptSupport need public _ID
unsigned int        _ID;
/// Lua reference id
int                 _luaID;


析构

Ref::~Ref()
{
#if CC_ENABLE_SCRIPT_BINDING
// if the object is referenced by Lua engine, remove it
if (_luaID)
{
ScriptEngineManager::getInstance()->getScriptEngine()->removeScriptObjectByObject(this);
}
else
{
ScriptEngineProtocol* pEngine = ScriptEngineManager::getInstance()->getScriptEngine();
if (pEngine != NULL && pEngine->getScriptType() == kScriptTypeJavascript)
{
pEngine->removeScriptObjectByObject(this);
}
}
#endif
}


手贱对removeScriptObjectByObject多摁了几次f12

void LuaEngine::removeScriptObjectByObject(Ref* pObj)
{
_stack-><span style="color:#ff0000;"><strong>removeScriptObjectByObject</strong></span>(pObj);
ScriptHandlerMgr::getInstance()-><strong><span style="color:#33ccff;">removeObjectAllHandlers</span></strong>(pObj);
}


void LuaStack::<strong><span style="color:#ff0000;">removeScriptObjectByObject</span></strong>(Ref* pObj)
{
<span style="color:#ff0000;"><strong>toluafix_remove_ccobject_by_refid</strong></span>(_state, pObj->_luaID);
}


TOLUA_API int <span style="color:#ff0000;"><strong>toluafix_remove_ccobject_by_refid</strong></span>(lua_State* L, int refid)
{
void* ptr = NULL;
const char* type = NULL;
void** ud = NULL;
if (refid == 0) return -1;

// get ptr from tolua_refid_ptr_mapping
lua_pushstring(L, TOLUA_REFID_PTR_MAPPING);
lua_rawget(L, LUA_REGISTRYINDEX);                               /* stack: refid_ptr */
lua_pushinteger(L, refid);                                      /* stack: refid_ptr refid */
lua_rawget(L, -2);                                              /* stack: refid_ptr ptr */
ptr = lua_touserdata(L, -1);
lua_pop(L, 1);                                                  /* stack: refid_ptr */
if (ptr == NULL)
{
lua_pop(L, 1);
// Lua stack has closed, C++ object not in Lua.
// printf("[LUA ERROR] remove CCObject with NULL ptr, refid: %d\n", refid);
return -2;
}

// remove ptr from tolua_refid_ptr_mapping
lua_pushinteger(L, refid);                                      /* stack: refid_ptr refid */
lua_pushnil(L);                                                 /* stack: refid_ptr refid nil */
lua_rawset(L, -3);                     /* delete refid_ptr[refid], stack: refid_ptr */
lua_pop(L, 1);                                                  /* stack: - */

// get type from tolua_refid_type_mapping
lua_pushstring(L, TOLUA_REFID_TYPE_MAPPING);
lua_rawget(L, LUA_REGISTRYINDEX);                               /* stack: refid_type */
lua_pushinteger(L, refid);                                      /* stack: refid_type refid */
lua_rawget(L, -2);                                              /* stack: refid_type type */
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);                                                  /* stack: refid_type */

// remove type from tolua_refid_type_mapping
lua_pushinteger(L, refid);                                      /* stack: refid_type refid */
lua_pushnil(L);                                                 /* stack: refid_type refid nil */
lua_rawset(L, -3);                    /* delete refid_type[refid], stack: refid_type */
lua_pop(L, 1);                                                  /* stack: - */

// get ubox
luaL_getmetatable(L, type);                                     /* stack: mt */
lua_pushstring(L, "tolua_ubox");                                /* stack: mt key */
lua_rawget(L, -2);                                              /* stack: mt ubox */
if (lua_isnil(L, -1))
{
// use global ubox
lua_pop(L, 1);                                              /* stack: mt */
lua_pushstring(L, "tolua_ubox");                            /* stack: mt key */
lua_rawget(L, LUA_REGISTRYINDEX);                           /* stack: mt ubox */
};

// cleanup root
tolua_remove_value_from_root(L, ptr);

lua_pushlightuserdata(L, ptr);                                  /* stack: mt ubox ptr */
lua_rawget(L,-2);                                               /* stack: mt ubox ud */
if (lua_isnil(L, -1))
{
// Lua object has released (GC), C++ object not in ubox.
//printf("[LUA ERROR] remove CCObject with NULL ubox, refid: %d, ptr: %x, type: %s\n", refid, (int)ptr, type);
lua_pop(L, 3);
return -3;
}

// cleanup peertable
lua_pushvalue(L, LUA_REGISTRYINDEX);
lua_setfenv(L, -2);

ud = (void**)lua_touserdata(L, -1);
lua_pop(L, 1);                                                  /* stack: mt ubox */
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;
}

// clean userdata
*ud = NULL;

lua_pushlightuserdata(L, ptr);                                  /* stack: mt ubox ptr */
lua_pushnil(L);                                                 /* stack: mt ubox ptr nil */
lua_rawset(L, -3);                             /* ubox[ptr] = nil, stack: mt ubox */

lua_pop(L, 2);
//printf("[LUA] remove CCObject, refid: %d, ptr: %x, type: %s\n", refid, (int)ptr, type);
return 0;
}


void ScriptHandlerMgr::<span style="color:#00cccc;"><strong>removeObjectAllHandlers</strong></span>(void* object)
{
if (NULL == object || _mapObjectHandlers.empty())
return;

auto iter = _mapObjectHandlers.find(object);

if (_mapObjectHandlers.end() != iter)
{
if (!iter->second.empty())
{
auto iterVec = iter->second.begin();
for (; iterVec != iter->second.end(); ++iterVec)
{
LuaEngine::getInstance()->removeScriptHandle<span style="color:#ffffff;">r</span>(iterVec->second);
}
(iter->second).clear();
}
_mapObjectHandlers.erase(iter);
}
}


最后还有一段

typedef void (Ref::*SEL_CallFunc)();
typedef void (Ref::*SEL_CallFuncN)(Node*);
typedef void (Ref::*SEL_CallFuncND)(Node*, void*);
typedef void (Ref::*SEL_CallFuncO)(Ref*);
typedef void (Ref::*SEL_MenuHandler)(Ref*);
typedef void (Ref::*SEL_SCHEDULE)(float);

#define callfunc_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFunc>(&_SELECTOR)
#define callfuncN_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFuncN>(&_SELECTOR)
#define callfuncND_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFuncND>(&_SELECTOR)
#define callfuncO_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFuncO>(&_SELECTOR)
#define menu_selector(_SELECTOR) static_cast<cocos2d::SEL_MenuHandler>(&_SELECTOR)
#define schedule_selector(_SELECTOR) static_cast<cocos2d::SEL_SCHEDULE>(&_SELECTOR)


















































第一次写博客,主要是为了记录学习过程,做个笔记。要是哪位大神看见了有什么不对的地方还望指出。















































内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: