您的位置:首页 > 编程语言 > Lua

How to use bindings-generator to generate lua binding automatically

2014-08-16 22:34 405 查看

How to use bindings-generator to generate lua binding automatically

Since cocos2d-x 3.0, we use
bindings-generator to generate lua bindings for c++ automatically.

The bindings-generator is based on tolua++, you could config the ini file in the
tools/tolua directory and then run the genbindings.py script to generate the binding code. By using this method, it greatly reduce the configuration work of writing pkg files.

Next, let's take a CustomClass as an example, we will show you how to use the bindings-generator to generate bindings.

Create the CustomClass

Here is the code snippets:

// CustomClass.h

#ifndef __CUSTOM__CLASS

#define __CUSTOM__CLASS

#include "cocos2d.h"

namespace cocos2d {
class CustomClass : public cocos2d::Ref
{
public:

CustomClass();

~CustomClass();

static cocos2d::CustomClass* create();

bool init();

CREATE_FUNC(CustomClass);
};
} //namespace cocos2d

#endif // __CUSTOM__CLASS

(Note: To keep this page short and clean, we omit the cpp file and the bindings-generator only scan the header files.)

One thing you should keep in mind, the custom class should be inheritent from cocos2d::Ref class, this is mainly due to the fact that all the global object's creation and destruction are handled by the
REFID_PTR_MAPPING
map in c++ layer. If we inheritent the class from Ref, then its destructor will handle these dirty things.

Add a new cocos2dx_custom.ini file

Navigate to the tools/lua folder and create a new file named
cocos2dx_custom.ini
.

Here is the content of cocos2dx_custom.ini:

[cocos2dx_custom]

# the prefix to be added to the generated functions. You might or might not use this in your own

# templates

prefix = cocos2dx_custom

# 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 = cc

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

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/my -I%(cocosdir)s/cocos/2d -I%(cocosdir)s/cocos/base -I%(cocosdir)s/cocos/ui -I%(cocosdir)s/cocos/physics -I%(cocosdir)s/cocos/2d/platform -I%(cocosdir)s/cocos/2d/platform/android -I%(cocosdir)s/cocos/math/kazmath -I%(cocosdir)s/extensions -I%(cocosdir)s/external -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s

cocos_flags = -DANDROID -DCOCOS2D_JAVASCRIPT

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 = %(cocosdir)s/cocos/my/CustomClass.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 = CustomClass.*

# 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

All of the config files under tools/tolua are the same format. Here is the list which you should care when writing your own ini file:

[title]: To config the title which will by used by the tools/tolua/gengindings.py scripts. Generally, the title could be the file name.
prefix: To config the prefix of a function name, generally, we also use the file name as the prefix.
target_namespace: To config the module name in scripting layer. Here we use the
cc
as the module name, when you want to ref a name in scripting layer, you must put a prefix named
cc
in front of the name. For example, the
CustomClass
could be reference as
cc.CustomClass
.
headers: To config all the header files needed for parsing and the %(cocosdir)s is the engine root path of cocos2d-x.
classes: To config all the classes needed to bind. Here it supports regular expression. So we could set MyCustomClass.* here, for looking more specified usage, you could ref to
tools/tolua/cocos2dx.ini
.

skip: To config the functions needed to be omit. Now the bindings-generator can't parse
void*
type and also the delegate type, so these types needed to be bind manually. And at this circumstance, you should omit all these types first and then to bind them manually. You could ref to the config files under path
cocos/scripting/lua-bindings/auto
.

rename_functions: To config the functions need to be renamed in the scripting layer. Due to some reasons, developers want more scripting friendly API, so the config option is for this purpose.

rename_classes: Not used any more.

remove_prefix: Not used any more.

classes_have_no_parents: To config the parent class needed to be filter. This option is seldom modified.

abstract_classes: To config the classes whose public constructor don't need to be exported.

script_control_cpp:yes. To config whether the scripting layer manage the object life time or not. If no, then the c++ layer cares about their life time.

Now, it is imperfect to control native object's life time in scripting layer. So you could simply leave it to
no.

Modify the
tools/tolua/genbindings.py
scripts

Open tools/tolua/genbindings.py and find the
cmd_args
option and add a new line:

'cocos2dx_custom.ini' : ('cocos2dx_custom', 'lua_cocos2dx_custom'), \

Run the
tools/tolua/genbindings.py
scripts

After running the
tools/tolua/genbindings.py
, there will be two more files under directory
cocos/scripting/lua-bindings/auto
:

lua_cocos2dx_custom_auto.cpp
lua_cocos2dx_custom_auto.h


Call the binding fuctions

Open the
lua_cocos2dx_custom_auto.h
and you will find a global function declaration:

register_all_cocos2dx_custom(lua_State* tolua_S);

If should call this function at a proper place(usually we call this function in the AppDelegate.cpp file). After calling this method, you will be able to use all the exported Lua functions. One more thing, when you call the register method, you should be
sure that the Lua stack top element is
_G
.

Summary

As you can see, it's easy to generate lua bindings from c++ code by using the bindings-generator.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: