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