Python调用C++类(续)

       这个月时间过得真快,又到了月底了。回想起来,一个月下来,学到的东西可不少啊,感觉很充实,很好!这次继续总结一下Python调用C++类的点点滴滴吧,开动!

     上次说过PyArg_ParseTuple可以很神奇的转化基类与子类的关系,原来这只是在某些条件下才成立的。例如:有这样一个类结构:

class SelectorProtocol
{
  //...
};
class CCobject
{
  //...
};
class CCNode: public SelectorProtocol, public CCObject
{
  //...
};

     一开始我打算使用PY_CCObejct*来作为PyArg_ParseTuple的参数,它本来的类型是个PY_CCNode,结果发现

PY_CCObject*->obj(CCObject*)的指针值是错误的,传进去C++函数崩了,原因大概如下:

SelectorProtocolA
CCObjectB

 CCNode的内存结构。上函数把Python结构里的CCObject*的起始位置转化到SelectorProtocol处,但是CCNode的内存起始位置是在SelectorProtocol那里,所以使用转化后的CCNode的基类SelectorProtocol的内存指向了前面的不明内存,这就出错了!所以以后处理这种问题可要当心了!也可以总结为:PyArg_ParseTuple只是把指针强转了。

 

     还有一个关于内存释放的死循环问题,原来为了保持脚本特性,在一个PY_Object*作用域外,会判断其C++对象在不在自动释放池里,是则不管了,否则delete掉。如果没有处理回调函数时能很好的处理,但是在PyObject*在CCObject中作为回调使用,例如:

     CCNode在释放中,即调用了delete this,在其父类CCObject中有个Py_XDecref(用来减少PyObject*计数),那时如果PyObject*(Python的CCNode对象)计数为一,一调用那个函数,计数变为0,立即调用Python的dealloc,里面又先进行自动释放池查找(原来自动释放池在每个循环都会清空,导致只在调用autorelease那个帧循环在,其他循环不在),结构肯定没找到,调用了delete其C++对象的操作,这刚好形成了一个环!因此现在取消了Python导出类析构函数的delete C++对象操作,这样如果是这样:myNode = CCNode() 没有使用自动释放池,会内存泄露。因此需要再myNode.autoRelease()才保证内存安全释放。或者考虑把PyObject*当做CCObject*的一个成员变量,PyObject*在CCObject*创建时创建,销毁时销毁,这样管理它就比较清晰,也不用担心内存泄露与Py_XDEREF导致的崩溃。现在为了解决那个Py_XDEREF问题,是手动把其计数为一,然后再使用该函数,保证了不内存泄露。

     Python调用C++类的细节真多,但自己实现确实学到不少东西,继续加油!GO!微笑

   

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值