User-defined Types

Source: Internet
Author: User

UserData

The UserData mechanism allows us to use custom data types in C in Lua. UserData represents a dynamically allocated memory, which stores data of custom types, uses UserData in Lua scripts, and works with the functions provided by C to manipulate UserData.

Define a player type:

struct _player {    int  ID;      Char name[];     int Account ;} Player;

Define all actions for the player:

Static int_index =1;Static intPlayer_new (lua_state*L) {Const Char* Name = lual_checkstring (L,1); intLen =strlen (name); Player* player = (player*) lua_newuserdata (L,sizeof(Player)); Use Lua_newuserdata to create a userdata and put it into the stack player->id = _index++; memcpy (Player->name, name, Len +1); A copy of the string is required, or the string is destroyed when the stack pops up.->account =0; return 1;}Static intPlayer_print (lua_state*L) {Player* player = (player*) lua_touserdata (L,1); printf ("player data:%d%s acount:%d \ n", Player->id, Player->name, player->Account ); return 0;}Static intPlayer_charge (lua_state*L) {Player* player = (player*) lua_touserdata (L,1); intAdd = Lual_checkint (L,2); Player->account + =add; return 0;}

Lua Code:

Local player = player. New ("xiaoming"= Player.) New ("xiaoqiang"101) Player.print (player) player.print (player1)

MetaTable

1. The same metatable represent the same type, so we also use a meta-table to indicate the type of UserData:

To set the meta table for UserData:

Const char* Class_name_player = "Player_class";

player* player = lua_newuserdata (L, sizeof (player));

Lua_newmetatable (L, Class_name_player); Create a new meta-table named Player_class, merged into the stack

Lua_setmetatable (L,-2); For position 2, set meta-table, meta-table UserData

How to use a meta-table for type determination:

Will

player* player = (player*) lua_touserdata (L, 1);

Switch

player* player = (player*) lua_checkudata (L, 1, Class_name_player); If the UserData type does not match, an error is thrown

2. In Lua, in addition to the types that can be labeled, and more importantly, the mock object-oriented, as with ordinary Lua objects, UserData can also use the meta-table mechanism to emulate object-oriented:

We first create a meta-table, we just need to put the object's methods on the meta-table, the most important thing is to set the meta-table __index meta-method:

Lual_newmetatable(L, class_name_player);//Create a new meta-table and merge it into the stack, which is stored in the global scope

...//Set some object methods

Lua_pushvalue(L,-1);//Copy meta-table

Lua_setfield(L,-2, "__index");//Set the __index meta-method of a meta-table to its own

When creating a new object, you only need to set the new object's meta-table to the metatable that you have created:

Lual_getmetatable(L, class_name_player);//Put the meta-table into the stack

Lua_setmetatable(L,-2);//Set meta-table, meta-table out stack

The above example should read:

C Code:

Static int_index =1;Const Char* Class_name_player ="Player_class";Static intPlayer_new (lua_state*l) {dump (L); Const Char* Name = lual_checkstring (L,1); intLen =strlen (name);        Dump (L); Player* player = (player*) lua_newuserdata (L,sizeof(Player));    Dump (L); Player->id = _index++; memcpy (Player->name, name, Len +1); Player->account =0;
Use the already created meta-table lual_getmetatable (L, Class_name_player); Lua_setmetatable (L,-2); return 1;}Static intPlayer_print (lua_state*L) {Player* player = (player*) lual_checkudata (L,1, Class_name_player); printf ("player data:%d%s acount:%d \ n", Player->id, Player->name, player->Account ); return 0;}Static intPlayer_charge (lua_state*L) {Player* player = (player*) lual_checkudata (L,1, Class_name_player); intAdd = Lual_checkint (L,2); Player->account + =add; return 0;}intLibopen_player (lua_state*L) {
Create a meta-table lual_newmetatable (L, Class_name_player); Lua_pushcfunction (L, player_print); Lua_setfield (L,-2,"Print"); Lua_pushcfunction (L, Player_charge); Lua_setfield (L,-2,"charge"); Lua_pushvalue (L,-1); Lua_setfield (L,-2,"__index"); Lua_settop (L,0);
The module has only one new method, Lua_newtable (L); Lua_pushcfunction (L, player_new); Lua_setfield (L,-2,"New"); Lua_setglobal (L,"Player"); return 1;}

Lua Code:

Local player = player. New ("xiaoming"= Player.) New ("xiaoqiang") player1:charge (20) player:charge (  ) Player:print () Player1:print ();

The lightweight UserData:

In contrast to the full USERDTA, the lightweight userdata is just a pointer to the C object, without the meta-table, which is an ordinary Lua object, just like number, so the lightweight userdata is not controlled by the LUA garbage collection mechanism and must manage the memory itself.

C Code:

player* player = nullptr; Static int player_pointer (lua_state* L) {    new  player ();    Player;    memcpy (player"wulin"6);    Player0;        Lua_pushlightuserdata (L, player);         return 1 ;}

Lua Code:

Local player1 = player.pointer ();p rint (player1);p rint (player2);

UserData Memory Recovery:

UserData belongs to the memory management mechanism of LUA, so there is no need to userdata memory problems, but if UserData uses some C memory objects and needs to delete them when UserData is deleted, Then Lua's memory recovery mechanism is not capable of. In this case, LUA provides us with a __gc meta method (for UserData only), and when UserData is deleted, the meta method is called and the UserData is passed in as a parameter, so we can delete the C object referenced in UserData.

Add a __gc meta-method to the player:

Static int player_delete (lua_state* L) {    player1, class_name_player);        printf ("delete something not in Lua memory ... player name:%s \ n", player->name) ;         return 0 ;}
intLibopen_player (lua_state*l) {lual_newmetatable (L, Class_name_player);    Lua_pushcfunction (L, player_print); Lua_setfield (L,-2,"Print");    Lua_pushcfunction (L, Player_charge); Lua_setfield (L,-2,"charge"); Lua_pushvalue (L,-1); Lua_setfield (L,-2,"__index");    Lua_pushcfunction (L, player_delete); Lua_setfield (L,-2,"__gc"); Add the __gc meta method Lua_settop (L,0);    Lua_newtable (L);    Lua_pushcfunction (L, player_new); Lua_setfield (L,-2,"New");    Lua_pushcfunction (L, Player_pointer); Lua_setfield (L,-2,"Pointer"); Lua_setglobal (L,"Player"); return 1;}

Lua Code:

Local player = player. New ("xiaoming") player:charge (=//  Forcing a garbage collection

User-defined Types

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.