Cocos Advanced Tutorials (1) Best practices for Lua to invoke custom C + + classes and functions

Source: Internet
Author: User
Tags lua one more line

First layer: pure C environment, register C function into LUA environment

A.lua file

Print (foo ())

A.C file

#include <lua.h>#include<lualib.h>#include<lauxlib.h>intFoo (lua_state *L) {  intn = Lua_tonumber (L,1); Lua_pushnumber (L, n+1); return 1;}intMain () {lua_state*l =Lua_open ();  Lual_openlibs (L); Lua_register (L,"Foo", foo); Lual_dofile (L,"A.lua");  Lua_close (L); return 0;}

After reading the code above, it is much easier to explain:

1, to register into the LUA environment, the function needs to be defined as this kind:int xxx(lua_State *L)
2, use lua_tonumber , and lua_tostring other functions, to obtain the incoming parameters, for example, lua_tonumber(L, 1) is to get the first parameter passed in, and the type is a number
3, using lua_pushnumber , and lua_pushstring so on, to press the return value into the LUA environment, because LUA support function returns multiple values, so you can push multiple return values into the LUA environment
4. The number returned by the final function indicates how many return values have been pressed into the LUA environment
5, using the lua_register macro definition to register this function into the LUA environment, LUA script can use it, done! It's so easy!

Second layer: In cocos2d-x environment, register C function into LUA environment

1, the key code in the AppDelegate.cpp file is as follows:

luastack* stack = engine->getluastack (); Luastack* stack = engine->*l = stack->"test_lua_bind" , Test_lua_bind);

2, Next, find a place to test_lua_bind write the function definition, even if you are done. If you pursue the elegance of a document organization, you should create a new. c file.

int test_lua_bind (lua_state *L) {    int1);     1 ;    Lua_pushnumber (L, number);     return 1 ;}

3, finished, you can now use the function in the Main.lua file test_lua_bind() :

Local i = Test_lua_bind ("" ) print ("".) ToString (i))

4, if it is a new. c file? AppDelegate.cpp test_lua_bind Delete the code of the function definition in the file and add it behind the head #include :

" test_lua_bind.h "

frameworks/runtime-src/Classescreate the file under the directory test_lua_bind.h , as follows:

extern " C "  "lua.h " "Lualib.h"}  int test_lua_bind (lua_state *l);

To create test_lua_bind.c the file again, the content is unchanged:

" test_lua_bind.h " int test_lua_bind (lua_state *L) {    int1);     1 ;    Lua_pushnumber (L, number);     return 1 ;}

Instead of using makefile, the Cocos2d-x project uses very intelligently the environment-specific engineering files to be used as a command-line compiler, such as using Xcode engineering files when compiling iOS or Macs, and using files when compiling Android Android.mk .

So, after you've added test_lua_bind.h and test_lua_bind.c files, open the project with Xcode and add the files to the project.

test_lua_bind.h test_lua_bind.cpp After adding the files to the Xcode project and then to the command line, the cocos compile -p mac compilation will be successful.

Layer Fourth: In a pure C + + environment, use tolua++ to register a C + + class into the LUA environment

The standard practice for using tolua++ is to:

1, prepare their own C + + class, how to write how to write
2, imitation of this kind of. h file, change a. pkg file, the specific format to follow the provisions of tolua++, such as the removal of all private members, etc.
3. Build a C + + class that is designed to bridge between C + + and LUA, use special function signatures to write its. h file,. cpp files do not write, wait for tolua++ to generate
4, to this bridge C + + class write a. pkg file, according to tolua++ special format to write, the purpose is to really do the C + + class to define in
5. Use tolua++ to generate the. cpp file for the bridging class at the command line
6, the program entry reference this bridge class, execute the generated bridge function, the LUA environment can use the real C + + class

tolua++ this kind of handwriting. pkg file way old and uncomfortable, so I did not study carefully, this set of processes 10 years ago in that era is not too much of a problem, how the author rules on how to use it, but in the 2014 today, any program architecture design is focused on low learning costs, Light weight, in line with the past habits, so tolua++ use I think is actually uncomfortable.

Below I take the minimum code to go through the tolua++ process, note that this is in a pure C + + environment, with any framework does not matter, do not consider memory release and other details:

MyClass.h

class MyClass {public:  MyClass () {};   int foo (int  i);};

MyClass.cpp

" MyClass.h " int Myclass::foo (int  i) {  return;}

Myclass.pkg

class myclass{  MyClass ();   int foo (int  i);};

MyLuaModule.h

extern " C "  "tolua++.h " "MyClass.h"  int tolua_myluamodule_open (lua_state* tolua_s);

Myluamodule.pkg

" MyLuaModule.h "  "myclass.pkg"

Main.cpp

extern "C"{#include<lua.h>#include<lualib.h>#include<lauxlib.h>} #include"MyLuaModule.h"intMain () {lua_state*l =Lua_open ();  Lual_openlibs (L);  Tolua_myluamodule_open (L); Lual_dofile (L,"Main.lua");  Lua_close (L); return 0;}

Main.lua

Local test = MyClass:new() print (Test:foo)

Execute at the command line first:

tolua++-O MyLuaModule.cpp myluamodule.pkg

This command is used to generate the bridging file MyLuaModule.cpp. Note the order of the-o parameter in the command line can not be placed arbitrarily, from this little thing can also be seen tolua++ ancient and difficult to use

Once the MyLuaModule.cpp file is generated, you can see the large number of bridges in it, such as, and tolua_beginmodule tolua_function so on. Later see these things are not unfamiliar, understand these functions just tolua++ used to do bridge the necessary code, simply look at the code, understand how tolua++ MyClass this C + + class registered into Lua:

At this point, the operation of the principle of tolua++ in the heart is translucent, nothing is:

1, write the class you write well
2, write a. pkg file, tell tolua++ what interfaces this class exposes to the LUA environment
3. Write a bridged. h and. pkg file, and let tolua++ to generate the bridge code
4, use this bridge code in the program, the class is registered into the LUA environment

Layer Fifth: Use Cocos2d-x to register C + + classes into the LUA environment

The working mechanism of the Bindings-generator script is:

1, do not have to write a bridge. Pkg and. h files, directly define an INI file, tell the script which classes of which methods to expose, register to the LUA Environment module name is what, it is equal to the original each class multiplied by 3 files of the workload into all classes only need 1. ini file
2. The method of generating the tolua++ tool is determined, and the Python script dynamically parses the C + + class and automatically generates the bridged. h and. CPP code without invoking the tolua++ command.
3, although the tolua++ command is no longer called, but the bottom layer still uses tolua++ library functions, for example tolua_function , Bindings-generator script generated code is almost the same as the use of the tolua++ tool generated

The Bindings-generator script has mastered the initiative of generating tolua++ Bridge code, not only saving a lot of. Pkg and. h files, but also better inserting custom code to achieve some special purposes in the COCOS2D-X environment, such as memory recycling. So Cocos2d-x from the 3.x began to give up the tolua++ and. Pkg and instead of writing their own bindings-generator script is very commendable clever practice.

Next, how to use the Bindings-generator script:

1, write their own C + + class, according to Cocos2d-x rules, inherit the Cocos2d::ref class, in order to use the Cocos2d-x memory recovery mechanism. Of course not, but not recommended, otherwise the release of objects in the LUA environment is troublesome.
2. Write an. ini file so that bindings-generator can tell how the C + + class is exposed based on this configuration file.
3, modify the Bindings-generator script, let it read this. ini file
4, execute Bindings-generator script, generate bridge C + + class method
5. Use Xcode to add the custom C + + class and the resulting bridging file to the project, otherwise it will not compile
6, modify the AppDelegate.cpp, execute the bridging method, the custom C + + class is registered into the LUA environment

Look at the steps very much, in fact, are ruthless and simple. Take one step at a step below.

The first is the custom C + + class. I'm used to saving files in the frameworks/runtime-src/Classes/ directory:

Frameworks/runtime-src/classes/myclass.h

" cocos2d.h " using namespace cocos2d; class  Public ref{public:  MyClass ()   {};   ~MyClass ()  {};   BOOL return true ; };  Create_func (MyClass);   int foo (int  i);};

Frameworks/runtime-src/classes/myclass.cpp

" MyClass.h " int Myclass::foo (int  i) {  return;}

Then write the. ini file. In the frameworks/cocos2d-x/tools/tolua/ directory you can see the genbindings.py script and a lot of. ini files, these are the actual execution environment of Bindings-generator. Find a little. ini file, copy it, and rename it to Myclass.ini. Most of the content can be done without change, here only the important parts that must be changed:

Frameworks/cocos2d-x/tools/tolua/myclass.ini

[Myclass]prefix            == myheaders          =% (Cocosdir) s/: /runtime-src/classes/myclass.hclasses          = MyClass

That is, specify the location of the MyClass.h file in Myclass.ini, specify the class to expose, and specify the module name to register into the LUA environment.

Notice, this place I stepped on a hole. If there is a macro definition in the. ini configuration file, macro_judgement = ... be especially careful that I copied it from the file for the first time, and cocos2dx_controller.ini did not notice that the resulting macro_judgement bridging class file was added to the add-on macro, which only works on iOS and Android platforms and is not valid for Mac platforms. Pay special attention to this.

Then modify the genbindings.py file in the vicinity of Line 129, add the Myclass.ini file:

frameworks/cocos2d-x/tools/tolua/genbindings.py

Cmd_args = {'cocos2dx.ini' : ('cocos2d-x'Lua_ Cocos2dx_auto'),             'myclass.ini' : ('  MyClass'lua_myclass_auto'),             ...

(In fact, this step can be omitted, as long as the genbindings.py script automatically search all INI files in the current directory, do not know the future Cocos2d-x team will not be optimized)

At this point, the preparation for bridging the file is done, and the genbindings.py script is executed:

Python genbindings.py

(On the Mac system may encounter the lack of YAML, cheetah package problems, install these Python package is simple, first sudo easy_install pip , the PIP installed, and then with the PIP various pip search , sudo pip install it can be)

After the genbindings.py script is executed successfully, the frameworks/cocos2d-x/cocos/scripting/lua-bindings/auto/ newly generated file is seen in the directory:

Every time the execution of the genbindings.py script is very long, because it to re-process all of the. ini files, it is recommended to boldly modify the script file, flexible processing, so that it can only process the required. ini file at a time, such as this looks like:

Look at the frameworks/cocos2d-x/cocos/scripting/lua-bindings/auto/ generated C + + Bridge file under the directory lua_MyClass_auto.cpp , with the name of the registration function register_all_MyClass() , which is the key function for registering the MyClass class into the LUA environment:

To edit a file frameworks/runtime-src/Classes/AppDelegate.cpp , first add a reference to the file in the file header lua_MyClass_auto.hpp :

Then add a call to the function in the correct code location register_all_MyClass :

Finally, before compiling, add the newly added C + + files to the Xcode project so that the compilation environment knows they exist:

There is also a small hole, because the file lua_MyClass_auto.cpp to reference the file MyClass.h , and the two files belong to different sub-projects, do not know each other the search path of the header file, so you need to manually modify cocos2d_lua_bindings.xcodeproj the configuration of the sub-project User Header Search Paths . Special attention to a total of a few ../ :

Finally, the entire project can be recompiled with cocos compile -p mac commands, and the compilation must be successful without an accident.

To modify the Main.lua file, try calling the MyClass class:

local test = My. Myclass:create ()print("" " .. Test:foo (©)

of the Register_all_cocos2dx_xxx (lua_state* tolua_s) function

Tolua_module (tolua_s,nullptr,0);
Tolua_beginmodule (TOLUA_S,NULLPTR);

Add the package name below

Tolua_module (tolua_s, "xxx", 0);
Tolua_beginmodule (tolua_s, "xxx");

Write one more line at the end

Tolua_endmodule (tolua_s);

2. After adding the LUA package name above, generate the binding file will error

Conversion wasn ' t set in ' Ns_map ' sections of the Conversions.yaml

Modify Frameworks/cocos2d-x/tools/bindings-generator/targets/conversions.yaml

Add a new package name message under Ns_map

"C + + Namespace::": "LUA package name."

Cocos Advanced Tutorials (1) Best practices for Lua to invoke custom C + + classes and functions

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.