Quick-Cocos2dx-Community lua绑定,lua调用C++ 类

笪德华
2023-12-01

http://blog.csdn.net/marpools/article/details/44341021#reply


这里有篇文章,看三和四。


按上面操作,文件都不缺少的,可以直接看  2. 和 3 .

记住:player3 来打开项目, 的类格式化后,放到他的源代码路径下面, 解释生成的lua 也要放到 api下面

player3  重新生成就可以了


player3    最后打开可能会出现, a nil value。


其实,我们用cocos2d-x-3.10,


D:\cocos\setup\Cocos2d-x\cocos2d-x-3.10\tools\tolua

genbindings.py   **.ini  来转换成 lua能够调用的 类。


其实就是通过D:\cocos\setup\Cocos2d-x\cocos2d-x-3.10\tools\tolua下提供:README.mdown.的说明来配置,最后生成lua  api函数。——这里不妨称这一套东西为c++ 转成 lua 的 解释器或者解释工具,转换工具也成。


我的环境:

win 7 64 位, Sublime Text 3, Quick-Cocos2dx-Community3.6(桌面快捷方式player3) vs 2013

Quick-Cocos2dx-Community 3.6 我没有转换成功,就用

cocos2d-x-3.10 转换,成功了

========================================================

以上才只是编译环境简单说明:

Quick-Cocos2dx-Community  最好,现在这个下面试试, 我的是在

G:\Game\Quick-Cocos2dx-Community\tools\tolua

下面,按住shift + 右键点击选择 “在此处打开命令窗口”直接运行  python  genbindings.py。 试试你的Quick-Cocos2dx-Community 能不能转换。


如果不行,也没有关系,这个时候,需要 cocos2d-x 引擎来处理, 我的是 cocos2d-x-3.10。

1. 把自己的类,.h  .cpp  放到 G:\ademo\frameworks\runtime-src\Classes  这个下面 “runtime-src\Classes”,  这里的工程是G:\下的 ademo,

(名字有点怪, demo 前面加个a 是便于 player3 打开项目是 目录 在最上面。)


接下来是 cocos2d-x-3.10解压安装目录下

D:\cocos\setup\Cocos2d-x\cocos2d-x-3.10\tools\tolua  

cocos2dx.ini   , genbindings.py 各复制一份 修改名称


修改下面的配置 :Pet.ini  Pet.py


[Pet]

prefix = Pet
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/editor-support -I%(cocosdir)s/cocos/platform/android

cocos_flags = -DANDROID

cxxgenerator_headers = 

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 = %(cocosdir)s/cocos/scripting/lua-bindings/auto/Pet.h

#headers = G:/aatestlua/frameworks/runtime-src/Classes/Pet.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 = Pet

# 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

注意:headers = %(cocosdir)s/cocos/scripting/lua-bindings/auto/Pet.h

我使用绝对路径没有成功。

我就顺便把自己的类 Pet.h 放到成才 lua 格式c++ 类同一目录下(runtime-src\Classes自己的c++类)


%(cocosdir)s/cocos/scripting/lua-bindings/auto/  就是这个目录


下面看Pet.py

这个里面 改的地方不多:

try:

        tolua_root = '%s/tools/tolua' % project_root
        output_dir = '%s/cocos/scripting/lua-bindings/auto' % project_root

        cmd_args = {
					#'cocos2dx.ini' : ('cocos2d-x', 'lua_cocos2dx_auto'), \
					'Pet.ini' : ('Pet', 'lua_pet_auto'), \
                    #'cocos2dx_assetsmanager.ini' : ('cocos2dx_assetsmanager', 'lua_cocos2dx_assetsmanager_auto'), \
                    #'cocos2dx_extension.ini' : ('cocos2dx_extension', 'lua_cocos2dx_extension_auto'), \
                    #'cocos2dx_ui.ini' : ('cocos2dx_ui', 'lua_cocos2dx_ui_auto'), \
                    #'cocos2dx_studio.ini' : ('cocos2dx_studio', 'lua_cocos2dx_studio_auto'), \
                    #'cocos2dx_spine.ini' : ('cocos2dx_spine', 'lua_cocos2dx_spine_auto'), \
                    #'cocos2dx_physics.ini' : ('cocos2dx_physics', 'lua_cocos2dx_physics_auto'), \
                    #'cocos2dx_experimental_video.ini' : ('cocos2dx_experimental_video', 'lua_cocos2dx_experimental_video_auto'), \
                    #'cocos2dx_experimental.ini' : ('cocos2dx_experimental', 'lua_cocos2dx_experimental_auto'), \
                    #'cocos2dx_controller.ini' : ('cocos2dx_controller', 'lua_cocos2dx_controller_auto'), \
                    #'cocos2dx_cocosbuilder.ini': ('cocos2dx_cocosbuilder', 'lua_cocos2dx_cocosbuilder_auto'), \
                    #'cocos2dx_cocosdenshion.ini': ('cocos2dx_cocosdenshion', 'lua_cocos2dx_cocosdenshion_auto'), \
                    #'cocos2dx_3d.ini': ('cocos2dx_3d', 'lua_cocos2dx_3d_auto'), \
                    #'cocos2dx_audioengine.ini': ('cocos2dx_audioengine', 'lua_cocos2dx_audioengine_auto'), \
                    #'cocos2dx_csloader.ini' : ('cocos2dx_csloader', 'lua_cocos2dx_csloader_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 *')


只需要 在 cmd_args = {  }中 把不需要的 注释掉,这样 解释起来 快点


tolua_root = '%s/tools/tolua' % project_root
output_dir = '%s/cocos/scripting/lua-bindings/auto' % project_root

这里的两个目录,上面的是 我修改 .ini  和 .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))
        if not os.path.exists(x86_llvm_path):
            x86_llvm_path = os.path.abspath(os.path.join(ndk_root, 'toolchains/llvm-3.4/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')))
        if not os.path.exists(x86_llvm_path):
            x86_llvm_path = os.path.abspath(os.path.join(ndk_root, 'toolchains/llvm-3.4/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 not os.path.exists(x64_llvm_path):
        x64_llvm_path = os.path.abspath(os.path.join(ndk_root, 'toolchains/llvm-3.4/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 = {
					#'cocos2dx.ini' : ('cocos2d-x', 'lua_cocos2dx_auto'), \
					'Pet.ini' : ('Pet', 'lua_pet_auto'), \
                    #'cocos2dx_assetsmanager.ini' : ('cocos2dx_assetsmanager', 'lua_cocos2dx_assetsmanager_auto'), \
                    #'cocos2dx_extension.ini' : ('cocos2dx_extension', 'lua_cocos2dx_extension_auto'), \
                    #'cocos2dx_ui.ini' : ('cocos2dx_ui', 'lua_cocos2dx_ui_auto'), \
                    #'cocos2dx_studio.ini' : ('cocos2dx_studio', 'lua_cocos2dx_studio_auto'), \
                    #'cocos2dx_spine.ini' : ('cocos2dx_spine', 'lua_cocos2dx_spine_auto'), \
                    #'cocos2dx_physics.ini' : ('cocos2dx_physics', 'lua_cocos2dx_physics_auto'), \
                    #'cocos2dx_experimental_video.ini' : ('cocos2dx_experimental_video', 'lua_cocos2dx_experimental_video_auto'), \
                    #'cocos2dx_experimental.ini' : ('cocos2dx_experimental', 'lua_cocos2dx_experimental_auto'), \
                    #'cocos2dx_controller.ini' : ('cocos2dx_controller', 'lua_cocos2dx_controller_auto'), \
                    #'cocos2dx_cocosbuilder.ini': ('cocos2dx_cocosbuilder', 'lua_cocos2dx_cocosbuilder_auto'), \
                    #'cocos2dx_cocosdenshion.ini': ('cocos2dx_cocosdenshion', 'lua_cocos2dx_cocosdenshion_auto'), \
                    #'cocos2dx_3d.ini': ('cocos2dx_3d', 'lua_cocos2dx_3d_auto'), \
                    #'cocos2dx_audioengine.ini': ('cocos2dx_audioengine', 'lua_cocos2dx_audioengine_auto'), \
                    #'cocos2dx_csloader.ini' : ('cocos2dx_csloader', 'lua_cocos2dx_csloader_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()


接下来, 开始 按住 shift键  右键 单击当前 文件夹 空白  选中 “当前窗口打开命令窗口”


输入:  python Pet.py

成功是 会出现 lua binding succeeds.

接下来 会出现 四个文件,

D:\cocos\setup\Cocos2d-x\cocos2d-x-3.10\cocos\scripting\lua-bindings\auto  

lua格式的c++ 类 lua_pet_auto.hpp  lua_pet_auto.cpp

D:\cocos\setup\Cocos2d-x\cocos2d-x-3.10\cocos\scripting\lua-bindings\auto\api

lua_pet_auto_api.lua    Pet.lua

这里需要注意:有的 没有生成 Pet.lua  是因为你的 .ini 下面 class=  Pet  没有指定要生成的类。


2. 需要用 vs 2013 来检验  ,调用 。 本文开头的链接 将的很清楚,这里就不啰嗦了。


可能到最后,vs 2013 打开运行 没有问题,但是 lua 直接用 player3  打开工程  会有问题******(a nil value).

function MainScene:ctor()
    cc.ui.UILabel.new({
            UILabelType = 2, text = "Hello, World", size = 64})
        :align(display.CENTER, display.cx, display.cy)
        :addTo(self)


	pet = Pet:new()
		print(strhello);
		strhello = pet:getTestText();
	    local  mPet = pet:addTo(self)       

	    print("===============调用成功===================")

	    cc.ui.UILabel.new({
	        UILabelType = 2, text = strhello, size = 32})
	    :align(display.CENTER, display.cx, display.cy + 100)
	    :addTo(self)

end
你要确保你的vs工程下面 libluacocos2d -auto   : lua_pet_auto.cpp 和 lua_pet_auto.hpp  存在。

这个我是放在 player3  源代码 路径下的:G:\Game\Quick-Cocos2dx-Community\cocos\scripting\lua-bindings\auto

可以直接 右键属性, c++ 头文件路径导入 绝对路径 G:\ademo\frameworks\runtime-src\Classes\

Pet.h  Pet.cpp

这里配置成功后, 后面需要打开的另一个工程就不需要配置了。


你的工程 下(这里我的是ademo) 下面 右键属性 G:\Game\Quick-Cocos2dx-Community\cocos\scripting\lua-bindings\auto

lua_pet_auto.cpp 和 lua_pet_auto.hpp  存在

G:\Game\Quick-Cocos2dx-Community\cocos\scripting\lua-bindings\auto\api

lua_pet_auto_api.lua  和 Pet.lua   存在

就是 把 cocos2d-x-3.10 下成才的东西 player3 在放置一下,因为你是用 player3吗,对吧!


注意:你用的是player3  ,但此时,为什么没有成功,这是为什么呢?  嘿嘿。


虽说你的  lua_pet_auto.cpp 和 lua_pet_auto.hpp  也放到 player3 的资源目录下啦(G:\Game\Quick-Cocos2dx-Community\cocos\scripting\lua-bindings\auto

lua_pet_auto_api.lua  和 Pet.lua

也在 G:\Game\Quick-Cocos2dx-Community\cocos\scripting\lua-bindings\auto\api 下了。


为什么呢?  

—— vs  打开工程   重新构建 ,build all 。 把所有的东西 整合。

因为 你用的 player3 ,是编译生成好的 。


3. 那好,我们来操作....

G:\Game\Quick-Cocos2dx-Community\quick\player

找到   proj.win32  vs 打开 解决方案 player.sln      重新 生成解决方案。


返回到上级目录 :G:\Game\Quick-Cocos2dx-Community\quick\player

win32  文件夹  ,就是 你的 player3(桌面没有的 ,右键桌面快捷方式)


重新生成解决方案后,打开看看,是不是成功了。


注意:vs 打开 解决方案 player.sln  下 项目 libluacocos2d  和你工程的  应该是一样的, 这也是上面我们提到的你会用到的。

只需要 player3 工程 下 class 右键添加 

G:\Game\Quick-Cocos2dx-Community\quick\player\Classes\ Pet.h  Pet.cpp   这里是从你的工程下 “\frameworks\runtime-src\Classes” 下哪来的

这也是 为什么 开始 让你 Quick-Cocos2dx-Community 下试试 能不能运行成功的原因, 成功了,就不需要 cocos2d-x-3.10 来生成


直接 在G:\Game\Quick-Cocos2dx-Community\tools\tolua  生成, 后面不要 复制过来复制过去了。


好了完了。


补充:

http://www.cocoachina.com/bbs/read.php?tid=200145

vs 调用 自己的类注意事项:

bool AppDelegate::applicationDidFinishLaunching()
{
	LuaEngine * lua_engine = LuaEngine::getInstance();
	ScriptEngineManager::getInstance()->setScriptEngine(lua_engine);
	lua_State*  luaState = lua_engine->getLuaStack()->getLuaState();
	if (L)
	{
		lua_getglobal(luaState, "_G");
		register_all_Pet(luaState);
		lua_settop(luaState, 0);
	}
    //register custom function
    //LuaStack* stack = engine->getLuaStack();
    //register_custom_function(stack->getLuaState());
    
    //FileUtils::getInstance()->setResourceEncryptKeyAndSign("test", "XXTEA");
}

这里补上资源:http://download.csdn.net/detail/bible521125/9539325

或者 官方文档:
http://www.cocos.com/doc/tutorial/show?id=2547


其他文档
http://my.oschina.net/guyson/blog/338375

以上仅供参考,欢迎留言指正错误!  附上邮箱:545625405@qq.com

 类似资料: