【COCOS2DX-LUA 脚本开发之十四】解决自定义CPP类编译到ANDROID运行黑屏的问题!

简介:

唉,首先说点闲话 – -。Himi搞了不短的时间,这个问题一直没有解决,最后终于在张大(cocos2dx引擎开发者之一 张小明)的指导下解决了此问题。

本章基于上一篇  【COCOS2DX-LUA 脚本开发之十三】  与之前的项目整合 【Cocos2d-X(2.x) 游戏开发系列之二】cocos2dx最新2.x版本跨平台整合NDK+Xcode,Xcode编写&编译代码,Android导入打包运行即可!

在进入正文之前,讲解下一些基础知识:(当前Himi的版本是cocos2xx 2.1.2 hotfix)

第一部分:

编译过项目到Android的童鞋们肯定知道创建好的Android项目下的jni下的Android.mk 这个文件,如下:

 


  
  
  1. LOCAL_PATH := $(call my-dir) 
  2.   
  3. include $(CLEAR_VARS) 
  4.   
  5. LOCAL_MODULE := game_shared 
  6.   
  7. LOCAL_MODULE_FILENAME := libgame 
  8.   
  9. LOCAL_SRC_FILES := hellocpp/main.cpp \ 
  10.                    ../../Classes/AppDelegate.cpp 
  11.   
  12. LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes 
  13.   
  14. LOCAL_STATIC_LIBRARIES := curl_static_prebuilt                  
  15.   
  16. LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static 
  17. LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static 
  18. LOCAL_WHOLE_STATIC_LIBRARIES += cocos_lua_static 
  19. LOCAL_WHOLE_STATIC_LIBRARIES += cocos_extension_static 
  20.   
  21. include $(BUILD_SHARED_LIBRARY) 
  22.   
  23. $(call import-module,cocos2dx) 
  24. $(call import-module,CocosDenshion/android) 
  25. $(call import-module,scripting/lua/proj.android/jni) 
  26. $(call import-module,cocos2dx/platform/third_party/android/prebuilt/libcurl) 
  27. $(call import-module,extensions) 
 

这个文件中,主要我们关注如下几个配置:‘

1.  LOCAL_SRC_FILES  :  编译到Android的本地的类cpp或c,比如自定义了一个类HSprite.h  HSprite.cpp

那么需要添加到这个 LOCAL_SRC_FILES 中,如下:

 


  
  
  1. LOCAL_SRC_FILES := hellocpp/main.cpp \ 
  2.                    ../../Classes/AppDelegate.cpp \ 
  3.                    ../../Classes/HSprite.cpp 
 

 

2. LOCAL_C_INCLUDES  :编译的本地类所在的路径,例如你有一个HSprite类放在Himi的文件夹中,那么你可以如下形式添加:

 


  
  
  1. LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes \ 
  2.                     $(LOCAL_PATH)/../../Classes/Himi 
  3.   
  4. 那么在你其他的类进行引用Himi文件夹下的HSprite时,无需写完整路径,如下: 
  5. #include "Himi/HSprite.h" 
  6.   
  7. 可以直接如下导入: 
  8. #include "HSprite.h" 
 

3.     LOCAL_STATIC_LIBRARIES  : 添加所需要链接的静态库

 

本章需要关注的是如下的配置:

4.    call import-module    :   编译对应的模块!

       $(call import-module,cocos2dx)  :具体是从 NDK_MODULE_PATH 路径下的cocos2dx文件夹下的Android.mk

 

那么 NDK_MODULE_PATH 是指向哪里呢?哪里设置呢?下面详细讲解!

 

第二部分:

编译过项目到Android的童鞋们肯定也知道build_native.sh 这个文件,NDK_MODULE_PATH的路径也在此文件中进行设置, 如下图:

如下:

 


  
  
  1. APPNAME="Tuc4Android" 
  2.   
  3. # options 
  4.   
  5. buildexternalsfromsource= 
  6.   
  7. usage(){ 
  8. cat << EOF 
  9. usage: $0 [options] 
  10.   
  11. Build C/C++ code for $APPNAME using Android NDK 
  12.   
  13. OPTIONS: 
  14. -s  Build externals from source 
  15. -h  this help 
  16. EOF 
  17.   
  18. while getopts "sh" OPTION; do 
  19. case "$OPTION" in 
  20. s) 
  21. buildexternalsfromsource=1 
  22. ;; 
  23. h) 
  24. usage 
  25. exit 0 
  26. ;; 
  27. esac 
  28. done 
  29.   
  30. # paths 
  31.   
  32. if [ -z "${NDK_ROOT+aaa}" ];then 
  33. echo "please define NDK_ROOT" 
  34. exit 1 
  35. fi 
  36.   
  37. DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 
  38. # ... use paths relative to current directory 
  39. COCOS2DX_ROOT="/Users/slater/Documents/cocos2d-2.1rc0-x-2.1.2-hotfix" 
  40. APP_ROOT="/Users/slater/Desktop/TestUserCpp/TestUserCpp" 
  41. APP_ANDROID_ROOT="/Users/slater/Desktop/TestUserCpp/TestUserCpp/proj.android" 
  42.   
  43. echo "NDK_ROOT = $NDK_ROOT" 
  44. echo "COCOS2DX_ROOT = $COCOS2DX_ROOT" 
  45. echo "APP_ROOT = $APP_ROOT" 
  46. echo "APP_ANDROID_ROOT = $APP_ANDROID_ROOT" 
  47.   
  48. # make sure assets is exist 
  49. if [ -d "$APP_ANDROID_ROOT"/assets ]; then 
  50.     rm -rf "$APP_ANDROID_ROOT"/assets 
  51. fi 
  52.   
  53. mkdir "$APP_ANDROID_ROOT"/assets 
  54.   
  55. # copy resources 
  56. for file in "$APP_ROOT"/Resources/* 
  57. do 
  58. if [ -d "$file" ]; then 
  59.     cp -rf "$file" "$APP_ANDROID_ROOT"/assets 
  60. fi 
  61.   
  62. if [ -f "$file" ]; then 
  63.     cp "$file" "$APP_ANDROID_ROOT"/assets 
  64. fi 
  65. done 
  66.   
  67. # copy icons (if they exist) 
  68. file="$APP_ANDROID_ROOT"/assets/Icon-72.png 
  69. if [ -f "$file" ]; then 
  70.     cp "$file" "$APP_ANDROID_ROOT"/res/drawable-hdpi/icon.png 
  71. fi 
  72. file="$APP_ANDROID_ROOT"/assets/Icon-48.png 
  73. if [ -f "$file" ]; then 
  74.     cp "$file" "$APP_ANDROID_ROOT"/res/drawable-mdpi/icon.png 
  75. fi 
  76. file="$APP_ANDROID_ROOT"/assets/Icon-32.png 
  77. if [ -f "$file" ]; then 
  78.     cp "$file" "$APP_ANDROID_ROOT"/res/drawable-ldpi/icon.png 
  79. fi 
  80.   
  81. if [[ "$buildexternalsfromsource" ]]; then 
  82.     echo "Building external dependencies from source" 
  83.     "$NDK_ROOT"/ndk-build -C "$APP_ANDROID_ROOT" $* \ 
  84.         "NDK_MODULE_PATH=${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/source" 
  85. else 
  86.     echo "Using prebuilt externals" 
  87.     "$NDK_ROOT"/ndk-build -C "$APP_ANDROID_ROOT" $* \ 
  88.         "NDK_MODULE_PATH=${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/prebuilt" 
  89. fi 
 

在之前我们整合项目编译到Android时其中我们需要关注的是 COCOS2DX_ROOT、 APP_ROOT、 APP_ANDROID_ROOT这三个路径的设置。

那么本次我们关注的是最下方  NDK_MODULE_PATH  是用于配置搜索编译模块的基础路径! 此路径与第一部分的Android.mk中 call import-module  相关!

${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/prebuilt”

表示两个路径,一个是COCOS2DX_ROOT的路径,另外一个是COCOS2DX_ROOT路径下的/cocos2dx/platform/third_party/android/prebuilt

 

通过如上两个知识点的简单的介绍,大家可能会对编译过程更深一步的理解。

现在开始讲解本章重点:  解决自定义cpp类通过tolua++ binding LuaCocos2d后编译到Android运行黑屏(没有调用自定义cpp类)的问题!

如果大家没有自定义类binding到LuaCocos2d中那么编译Android绝对是正确运行的,但是难免会自定义一些类供lua脚本使用,一般我们可以通过tolua++进行binding到LuaCocos2d中(参考Himi的另外一篇文章:【COCOS2DX-LUA 脚本开发之四】使用tolua++编译pkg,从而创建自定义类让Lua脚本使用

当正确binding到LuaCocos2d后,我们iphone模拟器运行后一切正常,那么当编译到Android后,总是出现黑屏,并屏幕显示有0个精灵 !

错误出在哪里呢?!首先我们最容易想到的是检查看 Android项目下jni下的Android.mk中的LOCAL_SRC_FILES 是否包含了你自定义的类!确定是否参与编译了!

如果确定参与编译了,并Android项目能正常运行,但是还是运行黑屏的话,那么你可以打印lua中调用的自定义类!最后会发现打印语句编译到Android后,根本没打印!基本上那就可以判定是LuaCocos2d这个类中并没有binding你自定义类!

有些童鞋就奇怪说可以确定xcode项目下的LuaCocos2d类中确实binding了自定义类啊!!

是的,但是你看到的只是ios项目所用的LuaCocos2d, 真正编译到Android后的LuaCocos2d根本不是ios项目下的LuaCocos2d这个类!!

那么到底是哪里的LuaCocos2d被编译到Android了呢?其实不难发现,通过Android.mk中看到编译lua模块的语句:

$(call import-module,scripting/lua/proj.android/jni)   : 我们可以知道它指向cocos2dx引擎下的scripting/lua/proj.android/jni/Android.mk

路径如下:

QQ20130427-1

 

打开后内容如下:

 


  
  
  1. LOCAL_PATH := $(call my-dir) 
  2. include $(CLEAR_VARS) 
  3.   
  4. LOCAL_MODULE    := cocos_lua_static 
  5.   
  6. LOCAL_MODULE_FILENAME := liblua 
  7.   
  8. LOCAL_SRC_FILES :=../../lua/lapi.c \ 
  9.                   ../../lua/lauxlib.c \ 
  10.           ../../lua/lbaselib.c \ 
  11.           ../../lua/lcode.c \ 
  12.           ../../lua/ldblib.c \ 
  13.           ../../lua/ldebug.c \ 
  14.           ../../lua/ldo.c \ 
  15.           ../../lua/ldump.c \ 
  16.           ../../lua/lfunc.c \ 
  17.           ../../lua/lgc.c \ 
  18.           ../../lua/linit.c \ 
  19.           ../../lua/liolib.c \ 
  20.           ../../lua/llex.c \ 
  21.           ../../lua/lmathlib.c \ 
  22.           ../../lua/lmem.c \ 
  23.           ../../lua/loadlib.c \ 
  24.           ../../lua/lobject.c \ 
  25.           ../../lua/lopcodes.c \ 
  26.           ../../lua/loslib.c \ 
  27.           ../../lua/lparser.c \ 
  28.           ../../lua/lstate.c \ 
  29.           ../../lua/lstring.c \ 
  30.           ../../lua/lstrlib.c \ 
  31.           ../../lua/ltable.c \ 
  32.           ../../lua/ltablib.c \ 
  33.           ../../lua/ltm.c \ 
  34.           ../../lua/lua.c \ 
  35.           ../../lua/lundump.c \ 
  36.           ../../lua/lvm.c \ 
  37.           ../../lua/lzio.c \ 
  38.           ../../lua/print.c \ 
  39.           ../../tolua/tolua_event.c \ 
  40.           ../../tolua/tolua_is.c \ 
  41.           ../../tolua/tolua_map.c \ 
  42.           ../../tolua/tolua_push.c \ 
  43.           ../../tolua/tolua_to.c \ 
  44.           ../../cocos2dx_support/CCLuaBridge.cpp \ 
  45.           ../../cocos2dx_support/CCLuaEngine.cpp \ 
  46.           ../../cocos2dx_support/CCLuaStack.cpp \ 
  47.           ../../cocos2dx_support/CCLuaValue.cpp \ 
  48.           ../../cocos2dx_support/Cocos2dxLuaLoader.cpp \ 
  49.           ../../cocos2dx_support/LuaCocos2d.cpp \ 
  50.           ../../cocos2dx_support/tolua_fix.c 
  51.   
  52. LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../lua \ 
  53.                            $(LOCAL_PATH)/../../tolua \ 
  54.                            $(LOCAL_PATH)/../../cocos2dx_support  
  55.   
  56. LOCAL_C_INCLUDES := $(LOCAL_PATH)/ \ 
  57.                     $(LOCAL_PATH)/../../lua \ 
  58.                     $(LOCAL_PATH)/../../tolua \ 
  59.                     $(LOCAL_PATH)/../../../../cocos2dx \ 
  60.                     $(LOCAL_PATH)/../../../../cocos2dx/include \ 
  61.                     $(LOCAL_PATH)/../../../../cocos2dx/platform \ 
  62.                     $(LOCAL_PATH)/../../../../cocos2dx/platform/android \ 
  63.                     $(LOCAL_PATH)/../../../../cocos2dx/kazmath/include \ 
  64.                     $(LOCAL_PATH)/../../../../CocosDenshion/include 
  65.   
  66. LOCAL_CFLAGS += -Wno-psabi 
  67. LOCAL_EXPORT_CFLAGS += -Wno-psabi 
  68.   
  69. include $(BUILD_STATIC_LIBRARY) 
 

从这个mk文件的内容中我们可以看到参与编译的LuaCocos2d类是相对于当前Android.mk 路径的  ../../cocos2dx_support/LuaCocos2d.cpp \

从上面的附上的图可以清楚的看到这个路径,是当前Android.mk的路径的上两层后的目录下的cocos2dx_support的LuaCocos2d.cpp文件!

可能讲到这里,很多童鞋应该恍然大悟了吧!

虽然我们自定义类通过tolua++ binding到项目下的LuaCococs2d 中,但是参与Android编译的LuaCocos2d并不是你项目下的!

      OK,那下面给出几种解决方式:

      第一种:将我们项目下的已经binding好的LuaCococs2d类替换参与编译的LuaCococs2d类!

                     (注:LuaCococs2d.h中导入的自定义类路径,引用你项目下的对应类即可)

     

    第二种: 将编译的Lua模块的Android.mk中的参与编译的LuaCococs2d路径改成自己项目下的LuaCococs2d路径即可。

    

    第三种: 通过修改 NDK_MODULE_PATH 路径,将其指向我们项目下的libs路径,然后将参与编译的缺少模块copy到我们的项目下对应路径即可!

这个问题其实比较容易解决,但是主要的是理解原理!否则会越忙越乱!









本文转自 xiaominghimi 51CTO博客,原文链接:http://blog.51cto.com/xiaominghimi/1188481,如需转载请自行联系原作者
目录
相关文章
|
1月前
|
算法 数据处理 Android开发
掌握安卓性能优化的秘诀:电池寿命与运行效率的提升
【10月更文挑战第6天】 本文深入探讨了安卓应用开发中的性能优化技巧,重点分析了影响电池寿命和运行效率的关键因素,并提供了针对性的优化策略。通过代码优化、资源管理、后台任务处理等方法,开发者可以显著提升应用的续航能力和流畅度。同时,结合具体案例,展示了如何在实际开发中应用这些技巧,确保应用在各种场景下都能保持高效运行。本文旨在为安卓开发者提供实用的性能优化指导,助力其打造更优质的应用体验。
41 2
|
1月前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
72 0
|
10天前
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
|
12天前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
25 5
|
27天前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
75 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
1月前
|
XML 前端开发 Java
安卓应用开发中的自定义View组件
【10月更文挑战第5天】自定义View是安卓应用开发的一块基石,它为开发者提供了无限的可能。通过掌握其原理和实现方法,可以创造出既美观又实用的用户界面。本文将引导你了解自定义View的创建过程,包括绘制技巧、事件处理以及性能优化等关键步骤。
|
1月前
|
编译器 Android开发
配置环境变量,使CMakeLists.txt可直接使用Android NDK工具链编译项目
配置环境变量,使CMakeLists.txt可直接使用Android NDK工具链编译项目
|
1月前
|
Ubuntu Shell API
Ubuntu 64系统编译android arm64-v8a 的openssl静态库libssl.a和libcrypto.a
Ubuntu 64系统编译android arm64-v8a 的openssl静态库libssl.a和libcrypto.a
|
开发工具 Android开发 iOS开发
|
Java Linux 开发工具
android 编译过程
引用:http://www.cnblogs.com/devinzhang/archive/2011/12/20/2294686.html http://blog.sina.com.cn/s/blog_7bee201901013nkk.html Android工程的编译过程 现在很多人想对Android工程的编译和打包进行自动化,比如建立每日构建系统、自动生成发布文件等等。
1001 0