Lua调用自定义C++类 以及打包到Android
2015-02-21 17:49
363 查看
本人参照网址:http://cn.cocos2d-x.org/tutorial/show?id=1749,下面记录下过程以及自己遇到的问题。
我定义的类以及头文件如下:
cpp文件
TestLua.py
按照上面的配置,结果发现运行时总是提示erros in parsing headers 但是还是能跑到最后。一开始以为是哪里的环境配置错了,纠结了好久,到最后找到网上一个帖子说,这个好像是正常的,不影响。好吧,都error了。
用coco ide编译runtime exe文件,结果lua_TestLua_auto总是提示找不到testlua文件。解决办法是选中lua_TestLua_auto文件,右键属性->c/c++->常规->附加包换目录,添加路径$(EngineRoot)../runtime-src/Classes,在运行就可以了
一下内容是从上面的网址直接复制过来的,用于作为参照打包apk
2、编译到Android手机出错
上面的配置完成后iOS的部分是可以正常运行的,但是这个时候编译android时不通过的。
因为 AppDelegate.cpp 里面调用的 register_all_MyClass(L) 方法在android不存在,android的项目里并没有配置去编译对应的 PanZoomLayer.cpp 文件和后续生成的 lua_custom_api_auto.cpp。
所以需要在android端配置Android.mk文件,让项目编译时去编译这两个C++文件才行。
(1)首先配置JNI下面的Android.mk文件,让JNI部分编译时去编译PanZoomLayer.cpp:
编辑 frameworks/runtime-src/proj.android/jni/Android.mk
在 LOCAL_SRC_FILES 参数的后面添加:(注意后面的 \ ,仅最后一行不加斜杠)
../../Classes/PanZoomLayer.cpp
在 LOCAL_C_INCLUDES 参数的后面添加:(注意后面的 \ ,仅最后一行不加斜杠)
$(LOCAL_PATH)/../../Classes
(2)然后配置 frameworks/cocos2d-x/cocos/scripting/lua-bindings/Android.mk文件。
在 LOCAL_SRC_FILES 参数的后面添加:(注意后面的 \ ,仅最后一行不加斜杠)
auto/lua_custom_api_auto.cpp
在 LOCAL_C_INCLUDES 参数的后面添加:(注意后面的 \ ,仅最后一行不加斜杠)
$(LOCAL_PATH)/../../../../runtime-src/Classes
(3)然后 Build-Runtime,将项目在Android端编译一下。
(4)若编译成功,就可以在Android手机上测试了!
编译Android文件apk
按照上面的办法,认真点是会成功的,编译到手机上是可以正确运行的。我就写错了点东西,结果出现了undefine testlua的错误。总之,这次总算是成功了,这还真花了不少时间呢。
我定义的类以及头文件如下:
#include "cocos2d.h" USING_NS_CC; class TestLua : public cocos2d::Node { public: TestLua(void); ~TestLua(void); virtual bool init(); //CREATE_FUNC(TestLua); static TestLua* create(); int show(int tag); protected: //bool init(){return true;}; };
cpp文件
#include "TestLua.h" TestLua::TestLua(void) { } TestLua::~TestLua(void) { } TestLua * TestLua::create() { TestLua * pRect = new TestLua(); if (pRect && pRect->init()) { pRect->autorelease(); return pRect; } CC_SAFE_DELETE(pRect); return nullptr; } bool TestLua::init() { if (!Node::init()) { return false; } return true; } int TestLua::show(int tag) { return tag + 100; }TestLua.ini文件
[TestLua] # the prefix to be added to the generated functions. You might or might not use this in your own # templates prefix = TestLua # create a target namespace (in javascript, this would create some code like the equiv. to `ns = ns || {}`) # all classes will be embedded in that namespace cpp_namespace = target_namespace = cc android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/include android_flags = -D_SIZE_T_DEFINED_ clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include clang_flags = -nostdinc -x c++ -std=c++11 cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/platform/android cocos_flags = -DANDROID cxxgenerator_headers = # extra arguments for clang extra_arguments = %(android_headers)s %(clang_headers)s %(cxxgenerator_headers)s %(cocos_headers)s %(android_flags)s %(clang_flags)s %(cocos_flags)s %(extra_flags)s # what headers to parse #headers = -I%(cocosdir)s/../../frameworks/runtime-src/Classes/TestLua.h headers = %(cocosdir)s/../runtime-src/Classes/TestLua.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^Menu*$". classes = TestLua # what should we skip? in the format ClassName::[function function] # ClassName is a regular expression, but will be used like this: "^ClassName$" functions are also # regular expressions, they will not be surrounded by "^$". If you want to skip a whole class, just # add a single "*" as functions. See bellow for several examples. A special class name is "*", which # will apply to all class names. This is a convenience wildcard to be able to skip similar named # functions from all classes. skip = rename_functions = rename_classes = # for all class names, should we remove something when registering in the target VM? remove_prefix = # classes for which there will be no "parent" lookup classes_have_no_parents = # base classes which will be skipped when their sub-classes found them. base_classes_to_skip = # classes that create no constructor # Set is special and we will use a hand-written constructor abstract_classes = # Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are 'yes' or 'no'. script_control_cpp = no
TestLua.py
#!/usr/bin/python # This script is used to generate luabinding glue codes. # Android ndk version must be ndk-r9b. import sys import os, os.path import shutil import ConfigParser import subprocess import re from contextlib import contextmanager def _check_ndk_root_env(): ''' Checking the environment NDK_ROOT, which will be used for building ''' try: NDK_ROOT = os.environ['NDK_ROOT'] except Exception: print "NDK_ROOT not defined. Please define NDK_ROOT in your environment." sys.exit(1) return NDK_ROOT def _check_python_bin_env(): ''' Checking the environment PYTHON_BIN, which will be used for building ''' try: PYTHON_BIN = os.environ['PYTHON_BIN'] except Exception: print "PYTHON_BIN not defined, use current python." PYTHON_BIN = sys.executable return PYTHON_BIN class CmdError(Exception): pass @contextmanager def _pushd(newDir): previousDir = os.getcwd() os.chdir(newDir) yield os.chdir(previousDir) def _run_cmd(command): ret = subprocess.call(command, shell=True) if ret != 0: message = "Error running command" raise CmdError(message) def main(): cur_platform= '??' llvm_path = '??' ndk_root = _check_ndk_root_env() # del the " in the path ndk_root = re.sub(r"\"", "", ndk_root) python_bin = _check_python_bin_env() platform = sys.platform if platform == 'win32': cur_platform = 'windows' elif platform == 'darwin': cur_platform = platform elif 'linux' in platform: cur_platform = 'linux' else: print 'Your platform is not supported!' sys.exit(1) if platform == 'win32': x86_llvm_path = os.path.abspath(os.path.join(ndk_root, 'toolchains/llvm-3.3/prebuilt', '%s' % cur_platform)) else: x86_llvm_path = os.path.abspath(os.path.join(ndk_root, 'toolchains/llvm-3.3/prebuilt', '%s-%s' % (cur_platform, 'x86'))) x64_llvm_path = os.path.abspath(os.path.join(ndk_root, 'toolchains/llvm-3.3/prebuilt', '%s-%s' % (cur_platform, 'x86_64'))) if os.path.isdir(x86_llvm_path): llvm_path = x86_llvm_path elif os.path.isdir(x64_llvm_path): llvm_path = x64_llvm_path else: print 'llvm toolchain not found!' print 'path: %s or path: %s are not valid! ' % (x86_llvm_path, x64_llvm_path) sys.exit(1) project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) cocos_root = os.path.abspath(os.path.join(project_root, '')) cxx_generator_root = os.path.abspath(os.path.join(project_root, 'tools/bindings-generator')) # save config to file config = ConfigParser.ConfigParser() config.set('DEFAULT', 'androidndkdir', ndk_root) config.set('DEFAULT', 'clangllvmdir', llvm_path) config.set('DEFAULT', 'cocosdir', cocos_root) config.set('DEFAULT', 'cxxgeneratordir', cxx_generator_root) config.set('DEFAULT', 'extra_flags', '') # To fix parse error on windows, we must difine __WCHAR_MAX__ and undefine __MINGW32__ . if platform == 'win32': config.set('DEFAULT', 'extra_flags', '-D__WCHAR_MAX__=0x7fffffff -U__MINGW32__') conf_ini_file = os.path.abspath(os.path.join(os.path.dirname(__file__), 'userconf.ini')) print 'generating userconf.ini...' with open(conf_ini_file, 'w') as configfile: config.write(configfile) # set proper environment variables if 'linux' in platform or platform == 'darwin': os.putenv('LD_LIBRARY_PATH', '%s/libclang' % cxx_generator_root) if platform == 'win32': path_env = os.environ['PATH'] os.putenv('PATH', r'%s;%s\libclang;%s\tools\win32;' % (path_env, cxx_generator_root, cxx_generator_root)) try: tolua_root = '%s/tools/tolua' % project_root output_dir = '%s/cocos/scripting/lua-bindings/auto' % project_root cmd_args = {'TestLua.ini' : ('TestLua', 'lua_TestLua_auto'), \ } target = 'lua' generator_py = '%s/generator.py' % cxx_generator_root for key in cmd_args.keys(): args = cmd_args[key] cfg = '%s/%s' % (tolua_root, key) print 'Generating bindings for %s...' % (key[:-4]) command = '%s %s %s -s %s -t %s -o %s -n %s' % (python_bin, generator_py, cfg, args[0], target, output_dir, args[1]) _run_cmd(command) if platform == 'win32': with _pushd(output_dir): _run_cmd('dos2unix *') print '---------------------------------' print 'Generating lua bindings succeeds.' print '---------------------------------' except Exception as e: if e.__class__.__name__ == 'CmdError': print '---------------------------------' print 'Generating lua bindings fails.' print '---------------------------------' sys.exit(1) else: raise # -------------- main -------------- if __name__ == '__main__': main()
按照上面的配置,结果发现运行时总是提示erros in parsing headers 但是还是能跑到最后。一开始以为是哪里的环境配置错了,纠结了好久,到最后找到网上一个帖子说,这个好像是正常的,不影响。好吧,都error了。
用coco ide编译runtime exe文件,结果lua_TestLua_auto总是提示找不到testlua文件。解决办法是选中lua_TestLua_auto文件,右键属性->c/c++->常规->附加包换目录,添加路径$(EngineRoot)../runtime-src/Classes,在运行就可以了
一下内容是从上面的网址直接复制过来的,用于作为参照打包apk
2、编译到Android手机出错
上面的配置完成后iOS的部分是可以正常运行的,但是这个时候编译android时不通过的。
因为 AppDelegate.cpp 里面调用的 register_all_MyClass(L) 方法在android不存在,android的项目里并没有配置去编译对应的 PanZoomLayer.cpp 文件和后续生成的 lua_custom_api_auto.cpp。
所以需要在android端配置Android.mk文件,让项目编译时去编译这两个C++文件才行。
(1)首先配置JNI下面的Android.mk文件,让JNI部分编译时去编译PanZoomLayer.cpp:
编辑 frameworks/runtime-src/proj.android/jni/Android.mk
在 LOCAL_SRC_FILES 参数的后面添加:(注意后面的 \ ,仅最后一行不加斜杠)
../../Classes/PanZoomLayer.cpp
在 LOCAL_C_INCLUDES 参数的后面添加:(注意后面的 \ ,仅最后一行不加斜杠)
$(LOCAL_PATH)/../../Classes
(2)然后配置 frameworks/cocos2d-x/cocos/scripting/lua-bindings/Android.mk文件。
在 LOCAL_SRC_FILES 参数的后面添加:(注意后面的 \ ,仅最后一行不加斜杠)
auto/lua_custom_api_auto.cpp
在 LOCAL_C_INCLUDES 参数的后面添加:(注意后面的 \ ,仅最后一行不加斜杠)
$(LOCAL_PATH)/../../../../runtime-src/Classes
(3)然后 Build-Runtime,将项目在Android端编译一下。
(4)若编译成功,就可以在Android手机上测试了!
编译Android文件apk
按照上面的办法,认真点是会成功的,编译到手机上是可以正确运行的。我就写错了点东西,结果出现了undefine testlua的错误。总之,这次总算是成功了,这还真花了不少时间呢。
相关文章推荐
- Android中打包含有Activity以及资源文件的jar包在工程中调用
- 调用android系统的图库以及截图来让用户自定义界面背景
- quick cocos2dx 3.3rc1 如何Lua调用自定义C++类(二)------ 调用C++函数
- Android工程依赖:android中打包含有Activity以及资源文件的jar包在工程中调用
- Cocos2d-x下Lua调用自定义C++类和函数的最佳实践
- 【COCOS2DX-LUA 脚本开发之十四】解决自定义CPP类通过TOLUA++ BINDING LUACOCOS2D后编译到ANDROID运行黑屏(没有调用自定义CPP类)的问题!
- Cocos2d-x下Lua调用自定义C++类和函数的最佳实践
- CC3.2+Lua ——Lua调用自定义C++类
- Windows7 + VS2013 + Cocos Code IDE Lua调用自定义C++类
- Cocos2d-x下Lua调用自定义C++类和函数的最佳实践
- android中打包含有Activity以及资源文件的jar包在工程中调用
- lua调用自定义c++类
- 【COCOS2DX-LUA 脚本开发之十四】解决自定义CPP类通过TOLUA++ BINDING LUACOCOS2D后编译到ANDROID运行黑屏(没有调用自定义CPP类)的问题!
- 【COCOS2DX-LUA 脚本开发之十四】解决自定义cpp类通过tolua++ binding LuaCocos2d后编译到Android运行黑屏(没有调用自定义cpp类)的问题!
- android中打包含有Activity以及资源文件的jar包在工程中调用
- lua脚本调用cocos2dx项目中自定义的C++类
- Cocos2d-x下Lua调用自定义C++类和函数的最佳实践
- Cocos2d-x下Lua调用自定义C++类和函数的最佳实践
- Cocos2d-x下Lua调用自定义C++类和函数的最佳实践
- quick luabinding , Lua调用自定义C++类,