cocos2dx 导出c++类供lua使用
官方教程传送门 http://www.cocos2d-x.org/docs/manual/framework/native/wiki/how-to-use-bindings-generator/zh
- ..编辑 ini文件
- 修改py脚本内容
- 运行py工具
- 就可以使用了
目前还不会lua传 函数 给c++ 类 执行
ini文件
[network_srv]
# the prefix to be added to the generated functions. You might or might not use this in your own # templates prefix = network_srv # 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 target_namespace = android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/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 -U __SSE__ cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/platform/android -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/external -I%(cocosdir)s/cocos/scripting/lua-bindings/manual -I%(cocosdir)s/external/lua/lua -I%(cocosdir)s/external/lua 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 = C:/Users/hk/Documents/Cocos/CocosProjects/LuaTest/frameworks/runtime-src/Classes/network_srv.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 = network_srv NetMgr # 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
genbindings.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 = 'C:/Users/hk/Documents/Cocos/CocosProjects/LuaTest/frameworks/runtime-src/Classes' cmd_args = {'network_srv.ini' : ('network_srv', 'lua_network_srv_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 '---------------------------------' os.system("pause") else: raise # -------------- main -------------- if __name__ == '__main__': main()
测试代码
network_srv.h 文件 #ifndef network_srv___ #define network_srv___ #include "cocos2d.h" #include "network/HttpRequest.h" #include "network/HttpClient.h" #include "network/HttpResponse.h" using namespace cocos2d; using namespace cocos2d::network; using namespace std; class network_srv :public cocos2d::Ref { public: CREATE_FUNC(network_srv); bool init(){ return true; } network_srv() { this->retain(); } void run(); }; #define URL_BASE "http://127.0.0.1:8080/cocos/" //#define URL_BASE "http://qq771911064.oicp.net:8080/cocos/" #define DATA_MAX_LENGTH 100 class NetMgr { public: static NetMgr*getInstance(); /** * @brief new a HttpRequest * @param action such as "login?name=1&&pass=1" * @ */ void newRequest(const char* action); /** * @brief if isDone please call this to get data * @return data from srv * @ */ const char *getData(); /** * @brief check network is done or not * @return 0 is't completed * @retuen 1 completed */ int isDone(); private: NetMgr(); int __isDone;/*0 is's done,1 done*/ char _data[DATA_MAX_LENGTH]; }; #endif //
cpp代码 #include "network_srv.h" void network_srv::run() { NetMgr::getInstance()->newRequest("login?name=1&&pass=1"); } void NetMgr::newRequest(const char* action) { __isDone = 0; string url = URL_BASE; url += action; HttpRequest*request = new HttpRequest; request->setUrl(url.c_str()); request->setRequestType(HttpRequest::Type::GET); request->setResponseCallback([=](HttpClient*client, HttpResponse *respone) { if (respone->getResponseCode() != 200)return; vector<char>* buffer = respone->getResponseData(); CC_ASSERT(DATA_MAX_LENGTH > buffer->size(), " NetMgr buffer size overfloaw"); for (int i = 0; i < buffer->size(); i++) { _data[i] = (*buffer)[i]; } _data[buffer->size()] = '\0'; __isDone = 1; }); HttpClient::getInstance()->setTimeoutForConnect(10); HttpClient::getInstance()->send(request); request->release(); } NetMgr* NetMgr::getInstance() { static NetMgr* _netmgr__ = 0; if (_netmgr__ == 0) { _netmgr__ = new NetMgr; } return _netmgr__; } const char * NetMgr::getData() { __isDone = 0; return _data; } int NetMgr::isDone() { return __isDone; } NetMgr::NetMgr() { __isDone = 0; }
lua 代码 local function menuCallbackClose() if NetMgr:getInstance():isDone()==1 then release_print("recv data " .. NetMgr:getInstance():getData()) end end -- add handler for close item local menuToolsItem = rootNode:getChildByName("Button_1") menuToolsItem:addTouchEventListener(menuCallbackClose) srv = network_srv:create(); srv:run();