dragonbonesCPP 在 Android 5.x 上问题的解决
在 cocos2d-x 3.4 上遇到了一个诡异的问题,记录如下。
平台和版本
- 框架: cocos2d-x 3.4 final
- 设备: Nexus 4/5/7 with Android 5.0.1/5.0.2
- NDK version: r9d
问题描述
一个 dragonbonesCPP 骨骼动画,在 iOS、Windows、Mac OS X、Android with 4.x 上表现完全正常,但在 Android 5.x 下表现不正常。
具体表现为解析骨骼动画数据的时候,既不 crash,也没有任何报错信息,整个程序就停住了。
问题追溯
通过加入 log 信息,发现问题处在 XMLDataParser::parserDragonBonesData
方法中,如下所示:
1//.............
2DragonBonesData* XMLDataParser::parseDragonBonesData(const void *rawDragonBonesData, float scale) const
3{
4 CCLOG("Start parse dragonbones data.");
5 _armatureScale = scale;
6 const XMLElement *dragonBonesXML = static_cast<const XMLElement*>(rawDragonBonesData);
7 std::string version = dragonBonesXML->Attribute(ConstValues::A_VERSION.c_str());
8 CCLOG("Start parse A_VERSION.");
9 // TODO
10 /*
11 switch(version)
12 {
13
14 }
15 */
16 CCLOG("A_FRAME_RATE: %s .", ConstValues::A_FRAME_RATE.c_str());
17 //打印了上面一行log 之后,整个程序就停住了
18 _frameRate = dragonBonesXML->IntAttribute(ConstValues::A_FRAME_RATE.c_str());
19 CCLOG("Start parse A_FRAME_RATE %d.", _frameRate);
20 DragonBonesData *dragonBonesData = new DragonBonesData();
21 //................
IntAttribute
是 tinyxml2 提供的解析方法,继续追溯,发现程序在 tinyxml2 中的 XMLUtil::ToInt
方法中停住。
1//.............
2bool XMLUtil::ToInt(const char *str, int *value)
3{
4 CCLOG("XMLUtil::ToInt str: %s, value: %d", str, *value);
5 //打印了上面一行 log 之后,整个程序就停住了
6 if (DBTIXML_SSCANF(str, "%d", value) == 1)
7 {
8 CCLOG("XMLUtil::ToInt SSCANF true");
9 return true;
10 }
11
12 CCLOG("XMLUtil::ToInt SSCANF false");
13 return false;
14}
15//.............
而 DBTIXML_SSCANF 是一个宏,在 NDK 中被指向 sscanf
。
我本以为是 tinyxml2 的问题,但换了 github 最新版本的 tinyxml2 依然有同样问题,于是开始怀疑 NDK。
Google 一番之后,找到了一个关键的 issue 77988 。这里说到的情况和我碰到的几乎一模一样,看来这是 NDK 的 BUG 没错了:
I have found that any call into the standard library sscanf function will cause the application to lockup. My device is the Nexus 5 running Android 5.0 preview version hammerhead-lpx13d-preview-f7596f51.tgz
Steps to recreate the problem:
Make any call to sscanf, for example:
int v1 = 0; sscanf("1", "%d", &v1);
Notice that the application will not return from the call to sscanf and completely freeze without any error message generated
解决方案
方案1
升级 NDK 到 r10d ,该版本已经解决了这个问题:
Documented a fix to a libc++ sscanf/vsscanf hang that occurred in API level 21. The fix itself had been implemented in r10c. (Issue 77988)
但进行 NDK 连接的时候,我碰到了这样的报错信息:
/Volumes/HD1/Android/android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9/../../../../arm-linux-androideabi/bin/ld: error: /Volumes/HD1/Android/android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9/libgcc.a(pr-support.o): multiple definition of '_Unwind_GetRegionStart' /Volumes/HD1/Android/android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9/../../../../arm-linux-androideabi/bin/ld: /Volumes/HD1/Android/android-ndk-r10d/sources/cxx-stl/llvm-libc++/libs/armeabi/thumb/libc++_static.a(Unwind-EHABI.o): previous definition here /Volumes/HD1/Android/android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9/../../../../arm-linux-androideabi/bin/ld: error: /Volumes/HD1/Android/android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9/libgcc.a(pr-support.o): multiple definition of '_Unwind_GetLanguageSpecificData' /Volumes/HD1/Android/android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9/../../../../arm-linux-androideabi/bin/ld: /Volumes/HD1/Android/android-ndk-r10d/sources/cxx-stl/llvm-libc++/libs/armeabi/thumb/libc++_static.a(Unwind-EHABI.o): previous definition here collect2: error: ld returned 1 exit status make: *** [obj/local/armeabi/libcocos2dlua.so] Error 1
我没有去解决这个问题,因为还有下一个方案。
方案2
如果担心 cocos2d-x 3.4 和 NDK r10d 的兼容性,也可以修改 Android 的编译参数:
编辑 android 项目中的 Application.mk 文件:
vim frameworks/runtime-src/proj.android/jni/Application.mk
将第一行:
APP_STL := c++_static
改为:
APP_STL := gnustl_static
(全文完)
- 文章ID:2242
- 原文作者:zrong
- 原文链接:https://blog.zengrong.net/post/dragonbonescpp-on-android5/
- 版权声明:本作品采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可,非商业转载请注明出处(原文作者,原文链接),商业转载请联系作者获得授权。