问题描述: 在原生平台上使用spine时,如果在js端调用到某些特定接口,待spine释放后,js中会泄漏部分nativeptr对象。
举例:
spine::Slot类里面有两个Color成员和对应的访问接口:
public:
Color &getColor();
Color &getDarkColor();
private:
Color _color;
Color _darkColor;
我们来看下getColor和getDarkColor的binding函数:
static bool js_cocos2dx_spine_Slot_getDarkColor(se::State& s)
{
spine::Slot* cobj = (spine::Slot*)s.nativeThisObject();
SE_PRECONDITION2(cobj, false, "js_cocos2dx_spine_Slot_getDarkColor : Invalid Native Object");
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 0) {
spine::Color& result = cobj->getDarkColor();
ok &= native_ptr_to_rooted_seval<spine::Color>((spine::Color*)&result, &s.rval());
SE_PRECONDITION2(ok, false, "js_cocos2dx_spine_Slot_getDarkColor : Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 0);
return false;
}
SE_BIND_FUNC(js_cocos2dx_spine_Slot_getDarkColor)
static bool js_cocos2dx_spine_Slot_getColor(se::State& s)
{
spine::Slot* cobj = (spine::Slot*)s.nativeThisObject();
SE_PRECONDITION2(cobj, false, "js_cocos2dx_spine_Slot_getColor : Invalid Native Object");
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 0) {
spine::Color& result = cobj->getColor();
ok &= native_ptr_to_rooted_seval<spine::Color>((spine::Color*)&result, &s.rval());
SE_PRECONDITION2(ok, false, "js_cocos2dx_spine_Slot_getColor : Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 0);
return false;
}
SE_BIND_FUNC(js_cocos2dx_spine_Slot_getColor)
需要 注意的是上面两个binding函数中都用了native_ptr_to_rooted_seval这个接口,意味着result这个color对象在js中对应的js对象不能被js引擎gc,而只能由C++来管理内存释放。而Slot的_color, _darkColor成员的释放过程中并不会主动去NativePtrToObjectMap里面删除对应的js对象。因此造成泄漏。
类似的问题在spine里面还有多个,只需要满足以下要求 的就都可能出问题:
- 导出接口使用的是native_ptr_to_rooted_seval
- 实际的对象是作为类成员对象(不是指引)
- 在js中调用过这个binding的接口。
