[UPDATE] Touches TEST in Android crashes - Dynamic cast fails when inheriting from CCSprite

After the latest Cocos changes where dynamic cast were introduced, I am having the following issue:

I declared:

class TouchSprite : public CCSprite, public CCTargetedTouchDelegate

and in the onEnter function I am doing:

void TouchSprite::onEnter()
{
CCSprite::onEnter();
CCTouchDispatcher::sharedDispatcher()>addTargetedDelegate;
}
After tracing, I found that bool CCTouchHandler::initWithDelegate fails in
)
>retain();

because the dynamic cast fails and returns NULL.

The code works fine when compiled using Xcode in iOS, but fails in Android. Any ideas?

* Update: The touchesTest demo (which my code snippet is based on), crashes the same way in Android (runs fine in iPhone), I hope
this makes it easier for the team to find the issue.

Thanks!

Yes, it crashed in (dynamic_cast<CCObject*>(pDelegate))->retain().
#926 is created for it.

Thank you.

I do the following test:

  1. add

    dynamic_cast(this)->retain()

before

CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, true)

It also crashed at CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, true).

  1. change

    class Paddle : public CCSprite, public CCTargetedTouchDelegate

to

class Paddle : public CCTargetedTouchDelegate, public CCSprite

It also crashed.

CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, true) is called in other tests, but they are ok.
The difference is that Paddle inherits CCSprite, not CCLayer.

I don’t know why.

Hi Minggo,

Thanks for taking a look. The problem is that the way the paddle demo works is the cleanest way to track sprites touches.
Otherwise I’ll have to pass all the touch handling to the scene object which is not a clen way to handle this.

Do we have any C++ wizards in the forums who can help?

Thanks!

In MenuTest.h, MenuLayer1 also invoke CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, true), it works ok.
I change

class MenuLayer1 : public CCLayer

to

class MenuLayer1 : public CCLayer, public CCTextureProtocol

to make it inherits from multiple classes, it also works ok.

Both CCLayer and CCSprite inherit from multiple classes, and both of them inherit from CCNode.
So I think it is the matter with the content of CCSprite.

But I don’t know why.
It is so strange, because it works ok in Paddle.cpp, but fails in CCTouchHandler.cpp.

The problem is still there with CCKeypadDelegate.

I’m not sure on the perfect solution though.
In general rtti does not work over module boundaries: http://gcc.gnu.org/faq.html#dso (at least not in a safe and portable way)

I guess the reason why the layer approach works is, that CCKeypadDelegate (and CCTouchDelegate) are extended by CCLayer directly (i.e. library code).
While in the Paddle example the delegate is extendend by client code (i.e. in a different module).

So I guess there may be three solutions to this problem:

  • compile game and library code into one single shared library (or statically link cocos2d and cocosdenshion)
  • manually load the libraries using dlopen with the RTLD_GLOBAL flag (I havn’t seen a way to add flags to the java call. Also this solution probably isn’t really future-proof in case the internal file hierarchy changes)
  • remove rtti from the library

We can not remove rtti, because we have to use multiple inherit.
I think the best way is to build cocos2dx into a static library.