Lua Study Notes (16)

Source: Internet
Author: User

 

 

I read userdata for two days and wrote a hundred lines of code to get a little bit of information about userdata.

Userdata can be understood as user-defined data. It is data, not a type. To put it bluntly, it is a piece of memory. Through a Simple API, we can get a userdata:

View sourceprint?

Void * lua_newuserdata (lua_State * L, size_t size );

This API is clear at a glance, and the created userdata will be properly placed on the top of the lua stack.

The interesting thing is that we can apply for a memory managed by lua. I heard that the gc of lua is quite good, it would be nice if I could throw a lot of memory management work to lua. on the other hand, I think lua is really not good, but it is more reliable to manage the memory by myself, but I need to make lua more direct operation of a piece of memory applied by the C Module I wrote. in the face of two different needs, the mechanism provided by lua can allow us to respond one by one.

1. Apply for a large memory and put the instance in this memory.

2. Apply for a small memory segment, store the instance address in this memory, and place the instance in the memory requested by the C/C ++ module.

In Case 1, once the gc of lua recycles the memory, the C/C ++ instance is destroyed. In case of 2nd, the C/C ++ instance can continue to exist.

These two solutions may be used to solve actual problems, and 2nd cases are worth writing a complete example to study. But today, let's just look at the 1st cases.

To study the 1st cases, I plan to make a simple float array. Below are the definitions of arrays in C and some lua interfaces:

View sourceprint?

Struct LuaArray

View sourceprint?

{

Int size;

Float data [1]; // I did this for ease.

};

Void InitArray (lua_State * pState); // This function is not an interface provided to lua. It is only used for initialization.

Int NewArray (lua_State * pState );

Int ReleaseArray (lua_State * pState );

Int GetArrayValue (lua_State * pState );

Int SetArrayValue (lua_State * pState );

Int GetArrayLength (lua_State * pState );

Int SumArray (lua_State * pState );

The code for the InitArray function is as follows:

View sourceprint?

Static const char * luw.raytablename = "LuaArray ";

Static const luaL_Reg ArrayFunction [] =

{

{"_ Newindex", SetArrayValue },

{"_ Len", GetArrayLength },

{"_ Gc", ReleaseArray },

{"Get", GetArrayValue },

{"Sum", SumArray },

{"New", NewArray },

{NULL, NULL}

};

 

Void InitArray (lua_State * pState)

{

LuaL_register (pState, luw.raytablename, ArrayFunction );

Lua_pushvalue (pState,-1 );

Lua_setfield (pState,-2, "_ index ");

Lua_pop (pState, 1 );

};

We can use some macros similar to message ing in MFC to simplify luw.raytablename and ArrayFunction.

Here, I created a lua table and stored it in the context of lua_State as a meta table.

Once we have created this table, we can bind our userdata to this table. In this way, we can perform the operations specified by the userdata table in lua.

Let's take a look at the created code:

View sourceprint?

Int NewArray (lua_State * pState)

{

Int elemCount = luaL_checkint (pState, 1 );

Int memSize = sizeof (LuaArray) + elemCount * sizeof (float );

LuaArray * pUData = (LuaArray *) lua_newuserdata (pState, memSize );

PUData-> size = elemCount;

PUData-> data [0] = 0.0f;

For (int I = 1; I <= elemCount; ++ I)

PUData-> data [I] = 0.0f;

Lua_getglobal (pState, luw.raytablename );

Lua_setretriable (pState,-2 );

//----------------------------------------------------------------------------

// It has no special significance for gc.

Float * pExData = new float [10];

Memcpy_s (void *) pUData-> data, sizeof (float), (void *) & pExData, sizeof (float *));

//----------------------------------------------------------------------------

Return 1;

}

Row 3 creates userdata and stores the LuaArray structure on the front end.

In lua, we can use this code to create a LuaArray:

View sourceprint?

Arr = LuaArray. new (10) -- creates a LuaArray of 10 elements.

Set the value in LuaArray to obtain the value in LuaArray (all checks are omitted ):

View sourceprint?

Int SetArrayValue (lua_State * pState)

{

LuaArray * pUData = (LuaArray *) lua_touserdata (pState, 1); // you can perform some checks here.

Int idx = luaL_checkint (pState, 2 );

Float val = (float) luaL_checknumber (pState, 3 );

PUData-> data [idx] = val;

Return 0;

}

Int GetArrayValue (lua_State * pState)

{

LuaArray * pUData = (LuaArray *) lua_touserdata (pState, 1 );

Int idx = luaL_checkint (pState, 2 );

Lua_pushnumber (pState, (lua_Number) pUData-> data [idx]);

Return 1;

}

The code for setting and obtaining values in lua is as follows:

View sourceprint?

Armr [1] = 100

 

Print (arr: get (1) // the reason why no arr [1] exists is that the _ index attribute in the meta table is used to point to the meta table itself.

Other functions are similar. The interesting thing is the _ gc event.

All variables in lua are referenced. When an object does not have any variables referenced, it will be reclaimed by lua's gc.

Write this in lua, and the code will be recycled:

View sourceprint?

Arr = nil

In the C/C ++ function of the corresponding _ gc event, we can release the memory we just applied:

View sourceprint?

Int ReleaseArray (lua_State * pState)

{

LuaArray * pUData = (LuaArray *) lua_touserdata (pState, 1 );

Float * pExData;

Memcpy_s (void *) & pExData, sizeof (float *), (void *) pUData-> data, sizeof (float ));

 

Delete [] pExData;

 

Return 0;

}

The mechanism of userdata + retriable allows us to extend data and types for lua from the perspective of C/C ++. in this article, the use of this mechanism is only a simple experimental method. Many improvements can be added to a specific project to meet different needs.

Related Article

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.