0
点赞
收藏
分享

微信扫一扫

【COCOS2DX-LUA 脚本开发之十四】解决自定义CPP类通过TOLUA++ BINDING LUACOCOS2D后编译到ANDROID运行黑屏(没有调用自定义CPP类)的问题!

本站文章均为​​李华明Himi​​​原创,转载务必在明显处注明:(作者新浪微博:​​@李华明Himi​​​) 


                  width="150" height="210" frameborder="0" scrolling="no" src="http://widget.weibo.com/relationship/bulkfollow.php?language=zh_cn&uids=1916000601&wide=1&color=FFFFFF,FFFFFF,0082CB,666666&showtitle=0&showinfo=1&sense=0&verified=1&count=1&refer=http%3A%2F%2Fwww.himigame.com%2Flua-game%2F1388.html&dpc=1" style="border-width: 0px; margin: 0px; padding: 0px; font-family: arial, helvetica, clean, sans-serif;font-size:12px; line-height: 16px; text-align: left; ">



唉,首先说点闲话 – -。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 这个文件,如下:

LOCAL_PATH := $(call my-dir)​​       



​​include $(CLEAR_VARS)​​



​​LOCAL_MODULE := game_shared​​



​​LOCAL_MODULE_FILENAME := libgame​​



​​LOCAL_SRC_FILES := hellocpp/main.cpp \​​

​​../../Classes/AppDelegate.cpp​​



​​LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes​​



​​LOCAL_STATIC_LIBRARIES := curl_static_prebuilt ​​



​​LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static​​

​​LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static​​

​​LOCAL_WHOLE_STATIC_LIBRARIES += cocos_lua_static​​

​​LOCAL_WHOLE_STATIC_LIBRARIES += cocos_extension_static​​



​​include $(BUILD_SHARED_LIBRARY)​​



​​$(call import-module,cocos2dx)​​

​​$(call import-module,CocosDenshion/android)​​

​​$(call import-module,scripting/lua/proj.android/jni)​​

​​$(call import-module,cocos2dx/platform/third_party/android/prebuilt/libcurl)​​

​​$(call import-module,extensions)​​

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

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

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

LOCAL_SRC_FILES := hellocpp/main.cpp \​​       

​​../../Classes/AppDelegate.cpp \​​

​​../../Classes/HSprite.cpp​​

 

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

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes \​​       

​​$(LOCAL_PATH)/../../Classes/Himi​​



​​那么在你其他的类进行引用Himi文件夹下的HSprite时,无需写完整路径,如下:​​

​​#include "Himi/HSprite.h"​​



​​可以直接如下导入:​​

​​#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的路径也在此文件中进行设置, 如下图:

如下:

APPNAME=​​​​"Tuc4Android"​​



​​# options​​



​​buildexternalsfromsource=​​



​​usage(){​​

​​cat << EOF​​

​​usage: $0 [options]​​



​​Build C/C++ code ​​​​for​​​ ​​$APPNAME ​​​​using​​​ ​​Android NDK​​



​​OPTIONS:​​

​​-s Build externals from source​​

​​-h ​​​​this​​​ ​​help​​

​​EOF​​

​​}​​



​​while​​​ ​​getopts ​​​​"sh"​​​ ​​OPTION; ​​​​do​​

​​case​​​ ​​"$OPTION"​​​ ​​in​​

​​s)​​

​​buildexternalsfromsource=1​​

​​;;​​

​​h)​​

​​usage​​

​​exit​​​ ​​0​​

​​;;​​

​​esac​​

​​done​​



​​# paths​​



​​if​​​ ​​[ -z ​​​​"${NDK_ROOT+aaa}"​​​ ​​];then​​

​​echo ​​​​"please define NDK_ROOT"​​

​​exit​​​ ​​1​​

​​fi​​



​​DIR=​​​​"$( cd "​​​​$( dirname ​​​​"${BASH_SOURCE[0]}"​​​ ​​)​​​​" && pwd )"​​

​​# ... use paths relative to current directory​​

​​COCOS2DX_ROOT=​​​​"/Users/slater/Documents/cocos2d-2.1rc0-x-2.1.2-hotfix"​​

​​APP_ROOT=​​​​"/Users/slater/Desktop/TestUserCpp/TestUserCpp"​​

​​APP_ANDROID_ROOT=​​​​"/Users/slater/Desktop/TestUserCpp/TestUserCpp/proj.android"​​



​​echo ​​​​"NDK_ROOT = $NDK_ROOT"​​

​​echo ​​​​"COCOS2DX_ROOT = $COCOS2DX_ROOT"​​

​​echo ​​​​"APP_ROOT = $APP_ROOT"​​

​​echo ​​​​"APP_ANDROID_ROOT = $APP_ANDROID_ROOT"​​



​​# make sure assets is exist​​

​​if​​​ ​​[ -d ​​​​"$APP_ANDROID_ROOT"​​​​/assets ]; then​​

​​rm -rf ​​​​"$APP_ANDROID_ROOT"​​​​/assets​​

​​fi​​



​​mkdir ​​​​"$APP_ANDROID_ROOT"​​​​/assets​​



​​# copy resources​​

​​for​​​ ​​file in ​​​​"$APP_ROOT"​​​​/Resources/*​​

​​do​​

​​if​​​ ​​[ -d ​​​​"$file"​​​ ​​]; then​​

​​cp -rf ​​​​"$file"​​​ ​​"$APP_ANDROID_ROOT"​​​​/assets​​

​​fi​​



​​if​​​ ​​[ -f ​​​​"$file"​​​ ​​]; then​​

​​cp ​​​​"$file"​​​ ​​"$APP_ANDROID_ROOT"​​​​/assets​​

​​fi​​

​​done​​



​​# copy icons (if they exist)​​

​​file=​​​​"$APP_ANDROID_ROOT"​​​​/assets/Icon-72.png​​

​​if​​​ ​​[ -f ​​​​"$file"​​​ ​​]; then​​

​​cp ​​​​"$file"​​​ ​​"$APP_ANDROID_ROOT"​​​​/res/drawable-hdpi/icon.png​​

​​fi​​

​​file=​​​​"$APP_ANDROID_ROOT"​​​​/assets/Icon-48.png​​

​​if​​​ ​​[ -f ​​​​"$file"​​​ ​​]; then​​

​​cp ​​​​"$file"​​​ ​​"$APP_ANDROID_ROOT"​​​​/res/drawable-mdpi/icon.png​​

​​fi​​

​​file=​​​​"$APP_ANDROID_ROOT"​​​​/assets/Icon-32.png​​

​​if​​​ ​​[ -f ​​​​"$file"​​​ ​​]; then​​

​​cp ​​​​"$file"​​​ ​​"$APP_ANDROID_ROOT"​​​​/res/drawable-ldpi/icon.png​​

​​fi​​



​​if​​​ ​​[[ ​​​​"$buildexternalsfromsource"​​​ ​​]]; then​​

​​echo ​​​​"Building external dependencies from source"​​

​​"$NDK_ROOT"​​​​/ndk-build -C ​​​​"$APP_ANDROID_ROOT"​​​ ​​$* \​​

​​"NDK_MODULE_PATH=${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/source"​​

​​else​​

​​echo ​​​​"Using prebuilt externals"​​

​​"$NDK_ROOT"​​​​/ndk-build -C ​​​​"$APP_ANDROID_ROOT"​​​ ​​$* \​​

​​"NDK_MODULE_PATH=${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/prebuilt"​​

​​fi​​

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

那么本次我们关注的是最下方  NDK_MODULE_PATH  是用于配置搜索编译模块的基础路径!

${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

路径如下:


打开后内容如下:

LOCAL_PATH := $(call my-dir)​​       

​​include $(CLEAR_VARS)​​



​​LOCAL_MODULE := cocos_lua_static​​



​​LOCAL_MODULE_FILENAME := liblua​​



​​LOCAL_SRC_FILES :=../../lua/lapi.c \​​

​​../../lua/lauxlib.c \​​

​​../../lua/lbaselib.c \​​

​​../../lua/lcode.c \​​

​​../../lua/ldblib.c \​​

​​../../lua/ldebug.c \​​

​​../../lua/ldo.c \​​

​​../../lua/ldump.c \​​

​​../../lua/lfunc.c \​​

​​../../lua/lgc.c \​​

​​../../lua/linit.c \​​

​​../../lua/liolib.c \​​

​​../../lua/llex.c \​​

​​../../lua/lmathlib.c \​​

​​../../lua/lmem.c \​​

​​../../lua/loadlib.c \​​

​​../../lua/lobject.c \​​

​​../../lua/lopcodes.c \​​

​​../../lua/loslib.c \​​

​​../../lua/lparser.c \​​

​​../../lua/lstate.c \​​

​​../../lua/lstring.c \​​

​​../../lua/lstrlib.c \​​

​​../../lua/ltable.c \​​

​​../../lua/ltablib.c \​​

​​../../lua/ltm.c \​​

​​../../lua/lua.c \​​

​​../../lua/lundump.c \​​

​​../../lua/lvm.c \​​

​​../../lua/lzio.c \​​

​​../../lua/print.c \​​

​​../../tolua/tolua_event.c \​​

​​../../tolua/tolua_is.c \​​

​​../../tolua/tolua_map.c \​​

​​../../tolua/tolua_push.c \​​

​​../../tolua/tolua_to.c \​​

​​../../cocos2dx_support/CCLuaBridge.cpp \​​

​​../../cocos2dx_support/CCLuaEngine.cpp \​​

​​../../cocos2dx_support/CCLuaStack.cpp \​​

​​../../cocos2dx_support/CCLuaValue.cpp \​​

​​../../cocos2dx_support/Cocos2dxLuaLoader.cpp \​​

​​../../cocos2dx_support/LuaCocos2d.cpp \​​

​​../../cocos2dx_support/tolua_fix.c​​



​​LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../lua \​​

​​$(LOCAL_PATH)/../../tolua \​​

​​$(LOCAL_PATH)/../../cocos2dx_support ​​



​​LOCAL_C_INCLUDES := $(LOCAL_PATH)/ \​​

​​$(LOCAL_PATH)/../../lua \​​

​​$(LOCAL_PATH)/../../tolua \​​

​​$(LOCAL_PATH)/../../../../cocos2dx \​​

​​$(LOCAL_PATH)/../../../../cocos2dx/include \​​

​​$(LOCAL_PATH)/../../../../cocos2dx/platform \​​

​​$(LOCAL_PATH)/../../../../cocos2dx/platform/android \​​

​​$(LOCAL_PATH)/../../../../cocos2dx/kazmath/include \​​

​​$(LOCAL_PATH)/../../../../CocosDenshion/include​​



​​LOCAL_CFLAGS += -Wno-psabi​​

​​LOCAL_EXPORT_CFLAGS += -Wno-psabi​​



​​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到我们的项目下对应路径即可!

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

举报

相关推荐

0 条评论