天天看点

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

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

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

第一部分:

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

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 中,如下:

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

如下:

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

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

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

if [ -f "$file" ]; then

    cp "$file" "$app_android_root"/assets

# copy icons (if they exist)

file="$app_android_root"/assets/icon-72.png

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

file="$app_android_root"/assets/icon-48.png

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

file="$app_android_root"/assets/icon-32.png

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

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_module_path=${cocos2dx_root}:${cocos2dx_root}/cocos2dx/platform/third_party/android/prebuilt"

在之前我们整合项目编译到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后,我们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

路径如下:

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

打开后内容如下:

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

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

继续阅读