Lua vs. C + + Interaction series: dynamically registering enum enum into Lua code, getting introspective information in LUA code at run time

Source: Internet
Author: User
Tags unique id



Introduction to LUA values and types in LUA 5.1 Reference Manual. Lua is a dynamic language, where variables have only values and no types in Lua. So variables in Lua do not need to be declared. So the value itself contains the type.
In fact, Lua contains a run-time type recognition that, through the type () function, can get the type of the value at run time.

Info from: Lua 5.1 Reference Manual Values and Types

Lua is a dynamically typed language. This means, that variables does not has the types; Only the values do. There is no type definitions in the language. All values carry their own type.

Type (variables)
Returns the type of its is only argument, coded as a string. The possible results of this function is "nil" (a string, not the value nil), "number", "string", "Boolean", "Table", "Fu Nction "," Thread ", and" UserData ".

In the C language feature itself, no run-time information is provided. The expansion set of the C language, the C + + language feature itself provides support for the runtime. In the C + + language, typeid (), Dynamic_case (), and other functions can obtain the type of introspection information.

In the Java language, support for introspective information is strong, and libraries such as spring are powerful libraries that are implemented through introspective information. Introspective information about the class is also provided in actionscript3.0. In game development, you can use introspection information to reflect class objects, including the game UI editor, which is implemented through introspective class information. C # is developed in the C++,java language and also provides strong support for run-time introspection. The introspective information for these languages is not detailed.


In the Python scripting language, the Pyobject class implementation mechanism and the LUA Lua_tvalue implementation mechanism type are bound by the type value int and the value. Although, in the Python and Lua languages, there is only a value, there is no type, but a function provided by the language can be obtained at run time to the type of the value.

In the LUA source code, the section selects some code related to run-time information:

The basic built-in type of 8 is provided in the LUA source code, and the basic built-in type of LUA changes little as Lua evolves. In a future article, the evolutionary history of the Lua type is described in detail.

/*** Basic types*/#define LUA_TNONE ( -1) #define Lua_tnil0#define lua_tboolean1#define Lua_tlightuserdata2#define LUA_ Tnumber3#define lua_tstring4#define lua_ttable5#define lua_tfunction6#define lua_tuserdata7#define LUA_TTHREAD8

Implementations of built-in types are implemented by binding values to types. The value is expressed in detail in the 5.0 implementation introduction of the LUA author.

typedef struct LUA_TVALUE {  value value_;//is used to indicate the value type of LUA, in the LUA author 5.0 Implementation There is a detailed description of  int tt_;//used to indicate the type, 1-8 is defined by the macro above} Tvalue;union Value {  gcobject *gc;    /* Collectable objects */  void *p;         /* Light UserData */  int b;           /* Booleans */  lua_cfunction F;/* light C functions */  Numfield         */numbers *};
In the LUA Code runtime, you can get the type of the value through type ():

Type (v)
Returns the type of its is only argument, coded as a string.
The possible results of this function is "nil" (a string, not the value nil), "number", "string", "Boolean", "Table", "Fu Nction "," Thread ", and" UserData ".

Note: The types of lightuserdata and full UserData are userdata.

Type (v) the key source code in Lua is as follows:

static int Luab_type (Lua_state *l) {  Lual_checkany (L, 1);  Lua_pushstring (L, Lual_typename (L, 1));  return 1;} /* Macros to access values *//Get the type # define TTYPE (o) with value binding (o)->tt)//return the corresponding string type by array # define TTYPENAME (x) luat_ typenames_[(x) + 1]luai_ddef const char *const luat_typenames_[lua_totaltags] = {  "no value",  "nil", "Boolean", U Datatypename, "number",  "string", "table", "function", Udatatypename, "thread",  "Proto", "upval"/  * These Last cases is used for tests only */};


This article refers to the Luaautoc open source project, and extracts part of the code, modified. This article mainly shows that the C language struct, enum and other structures are registered in LUA code, and the runtime information of the registered type can be obtained in LUA code.

by Lua_pushinteger (L, 0); Lua_setfield (L, Lua_globalsindex, prefix "Type_index"); To manage the generation of a unique type ID and store it in a global variable with a default value of 0.
By registering all the types in the global variables table, you can get the relevant information in Lua code, and you can introspect the C language custom type in LUA code.
The core of this paper is implemented by a global unique ID and a hash system of the LUA table itself. The code is simple. Serving.

Luademo.cpp:

extern "C" {#include "lua.h" #include "lauxlib.h" #include "lualib.h"} #define prefix "Prefix_"//author Orangeduck In his blog, the introspection mechanism in dynamic language is the core. Lua also uses type_id to indicate the type. This coincides with the author. TYPE_ID is generated dynamically by the runtime, starting from zero by default. You can get the type of the object at run time Id.//luaautoc has been successfully applied in the Orangeduck author's project.  void Luaa_open (lua_state* L) {//used to dynamically generate a unique ID for a type at run time, the default start value is 0. The value in the global variable table setting prefix "Type_index" defaults to 1, which is used to mark all types. Lua_pushinteger (L, 0);  Lua_setfield (L, Lua_globalsindex, prefix "Type_index"); In the global variables table, prefix "Type_ids" corresponds to the table structure. Called IDTable. Name-id lua_newtable (L);  Lua_setfield (L, Lua_globalsindex, prefix "Type_ids"); In the global variables table, prefix "Type_names" corresponds to the table structure. Called NameTable. Name-Name lua_newtable (L);  Lua_setfield (L, Lua_globalsindex, prefix "Type_names"); In the global variables table, prefix "type_sizes" corresponds to the table structure. Called sizetable. Name-size lua_newtable (L);       Lua_setfield (L, Lua_globalsindex, prefix "type_sizes"); With the above type, register enumstable,enum_sizestable,enums_valuestable in the registry to store the enumeration values in C//These as the core system in this example.  You can recognize the introspective information of a C-language user's custom struct structure at run time. Lua_newtable (L); Lua_setfield (L, lua_globalsindex, prefix "Enums "); Lua_newtable (L);  Lua_setfield (L, Lua_globalsindex, prefix "enums_sizes"); Lua_newtable (L); Lua_setfield (L, Lua_globalsindex, prefix "enums_values"); }//To illustrate this example of enum enum Week{monday,tuesday,wednesday,thursday,friday,saturday,sunday,};typedef Lua_integer luaA_Type;/ /Manage all registered types in the global variables table, you can get introspection information by name at run time//in the Global environment Type_idstable and type_namestable and type_values register type. If the type already exists in the Global environment table, return the type ID directly, otherwise register the new type///////////////////////////////////////////////////////////////////// Example with Week enumeration://_g[prefix_type_ids]["Week"]=weekid//_g[prefix_type_names][weekid]=weekname//_g[prefix_type_sizes][ Weekid]=weeksize//////////////////////////////////////////////////////////////////luaa_type LuaA_type_add (Lua_ state* L, const char* type, size_t size) {//Get in the Global environment table idtable, type name =id Lua_getfield (L, Lua_globalsindex, prefix "Type_ids"  );  Gets whether the type_name exists in IDTable Lua_getfield (L,-1, type);    Determine if there is an if (Lua_isnumber (L,-1)) {//If it already exists, the return type id luaa_type id = lua_tointeger (l,-1);    Lua_pop (L, 2); return ID    } else {//eject idtable and type associated ID lua_pop (L, 2);    Gets the automatically generated unique index that is automatically generated at run time.    Lua_getfield (L, Lua_globalsindex, prefix "Type_index"); Convert to integer luaa_type id = Lua_tointeger (l,-1);//Empty stack top Lua_pop (l, 1);//automatically generate next unique index id++;//press into virtual stack Lua_pushinteger (l    , id);//Set the generated unique index to ID, and stack lua_setfield (L, Lua_globalsindex, prefix "Type_index");   Get IDTable Lua_getfield (l, lua_globalsindex, prefix "Type_ids");//press the auto-generated unique ID into the stack lua_pushinteger (l, id);//index [key]= stack Top    Set Idtable[type]=id Lua_setfield (L,-2, type);    Lua_pop (L, 1);     Gets the type NameTable Lua_getfield (l, lua_globalsindex, prefix "type_names");//put the unique ID into the stack lua_pushinteger (l, id);//press the type name into the stack    Lua_pushstring (L, type);//Set index [below stack top]= stack top Nametable[id]=type lua_settable (L,-3);      Lua_pop (L, 1);    Lua_getfield (L, Lua_globalsindex, prefix "type_sizes");    Lua_pushinteger (L, id);    Lua_pushinteger (L, size);    Lua_settable (L,-3);    Lua_pop (L, 1);      return ID; }}//registers an enum type that is used to store enum values per enum//to Week enumerationExample://_g[prefix_enums]["Weekid"]=weekenumtable//_g[prefix_enums_values]["Weekid"]=weekenumvaluetable//_G[prefix_ enums_sizes]["Weekid"]=weekenumsizetablevoid luaa_enum_type (lua_state *l, Luaa_type type, size_t size) {Lua_getfield (  L, Lua_globalsindex, prefix "enums");  Lua_pushinteger (L, type);  Lua_newtable (L);  Lua_settable (L,-3);  Lua_pop (L, 1);  Lua_getfield (L, Lua_globalsindex, prefix "enums_values");  Lua_pushinteger (L, type);  Lua_newtable (L);  Lua_settable (L,-3);  Lua_pop (L, 1);  Enum_sizestable[name] Lua_getfield (L, Lua_globalsindex, prefix "enums_sizes");  Lua_pushinteger (L, type);  Lua_pushinteger (L, size);  Lua_settable (L,-3); Lua_pop (L, 1);} The actual registration of each value in the Enum enumeration into the registry//registers an enum type, which is used to store enum values per enum//With Week enumeration examples://_g[prefix_enums]["Weekid"]=weekenumtable//_g[ prefix_enums_values]["Weekid"]=weekenumvaluetable//_g[prefix_enums_sizes]["Weekid"]=WeekEnumSizeTable//////_G[ prefix_enums_sizes]["Weekid" ["Monday"]=monday//void luaa_enum_value_type (lua_state *l, luaa_type type, int lvaluE, const char* name) {//Get _g[prefix_enums]["Weekid"]=weekenumtable Lua_getfield (L, Lua_globalsindex, prefix "enums");  Lua_pushinteger (L, type);  Lua_gettable (L,-2);    if (!lua_isnil (L,-1)) {//store enum size Lua_getfield (l, lua_globalsindex, prefix "enums_sizes");    Lua_pushinteger (L, type);    Lua_gettable (L,-2);    size_t size = Lua_tointeger (L,-1);        Lua_pop (L, 2);    Lua_pushstring (L, name);    Lua_pushinteger (L, lvalue);    Lua_settable (l,-3);    Lua_getfield (L, Lua_globalsindex, prefix "enums_values");    Lua_pushinteger (L, type);    Lua_gettable (L,-2); size_t v =0;if (!lua_isnil (L,-1)) {v =lua_tonumber (l,-1);}    Lua_pushinteger (L, v);    Lua_getfield (L, -4, name);    Lua_settable (L,-3);    Lua_pop (L, 4);  Return  } lua_pop (L, 2);  Lua_pushfstring (L, "Luaa_enum_value:enum '%s ' not registered!", Luaa_typename (L, type)); Lua_error (L);} The actual registration of each value in the Enum enumeration into the registry//registers an enum type, which is used to store enum values per enum//With Week enumeration examples://_g[prefix_enums]["Weekid"]=weekenumtable//_g[ Prefix_enums_values]["Weekid"]=weekenumvaluetable//_g[prefix_enums_sizes]["Weekid"]=weekenumsizetable//////_G[prefix_enums_ sizes]["Weekid" ["Monday"]=monday//void luaa_enum_value_type (lua_state *l, luaa_type type, int lvalue, const char* Name  {//Get _g[prefix_enums]["Weekid"]=weekenumtable Lua_getfield (L, Lua_globalsindex, prefix "enums");  Lua_pushinteger (L, type);  Lua_gettable (L,-2);    if (!lua_isnil (L,-1)) {//store enum size Lua_getfield (l, lua_globalsindex, prefix "enums_sizes");    Lua_pushinteger (L, type);    Lua_gettable (L,-2);    size_t size = Lua_tointeger (L,-1);        Lua_pop (L, 2);    Lua_pushstring (L, name);    Lua_pushinteger (L, lvalue);    Lua_settable (l,-3);    Lua_getfield (L, Lua_globalsindex, prefix "enums_values");    Lua_pushinteger (L, type);    Lua_gettable (L,-2); size_t v =0;if (!lua_isnil (L,-1)) {v =lua_tonumber (l,-1);}    Lua_pushinteger (L, v);    Lua_getfield (L, -4, name);    Lua_settable (L,-3);    Lua_pop (L, 4);  Return  } lua_pop (L, 2); Lua_pushfstring (L, "LuaA_enum_value:enum '%s ' not registered! ", Luaa_typename (L, type)); Lua_error (L);} Using c language macros, the enum struct type in C language as String # # Luaa_type (l, type) Luaa_type_add (l, #type, sizeof (type))//define enum type # # Luaa_enum (l, type) Luaa_enum_type (L, Luaa_type (l, type), sizeof (type))//Register enumeration value # define Luaa_enum_value (L,enumtype, Enumvalue) Luaa_enum_value_type (L, Luaa_type (L,enumtype), enumvalue, #enumValue) int main (int argc, char **argv) {Lua_  state *l = Lua_open ();  /* Create state */Lual_openlibs (L);  Luaa_open (L);  Register enumeration type Luaa_enum (L,week);  Each enumerated value in the actual registered enum type Luaa_enum_value (L,week,monday);  Luaa_enum_value (L,week,tuesday);  Luaa_enum_value (L,week,wednesday);  Luaa_enum_value (L,week,thursday);  Luaa_enum_value (L,week,friday);  Luaa_enum_value (L,week,saturday);  Luaa_enum_value (L,week,sunday);  Lual_dofile (L, "Demo.lua");  Lua_close (L); return 1;}
Luademo.lua File Code:

Print ("=========")--Gets the type idlocal weekid =_g["Prefix_type_ids"] [Week] based on the registered enum name]--get run-time information local nameTable =_g[" Prefix_type_names "][weekid]local sizetable =_g[" prefix_type_sizes "][weekid]print (WeekId) print (nameTable) print ( sizetable) Local week= _g["Prefix_enums"][weekid]local weekvalue= _g["prefix_enums_values"][WeekId]local WeekSize = _G ["Prefix_enums_sizes"] [Weekid]print (Week) print (weekvalue) print (weeksize)--Get registered enumeration value print (Week.monday) print (week.tuesday) print ( Week.wednesday) print (week.thursday) print (week.friday) print (week.saturday) print (week.sunday)


The results of the operation are as follows:



This is the end of this article. Throw the jade, if the wrong place, please support, everyone share knowledge.

Lua vs. C + + Interaction series: dynamically registering enum enum into Lua code, getting introspective information in LUA code at run time

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.