userdata

Q:什么是 userdata ?
A:分为两类,full userdata 和 light userdata。Lua使用他们来表示C中的类型。

Q:两种”userdata”的区别?
A:

区别 full userdata light userdata
作用 通常用来表示C中的结构体。
一小段固定的内存区域
通常用来表示C中的指针(void *)
内存管理 由Lua的垃圾回收器管理 使用者需要关心其内存
元表 有独立的元表 没有独立的元表
创建 void _lua_newuserdata(lua_State _L, size_t size) lua_pushlightuserdata(lua_State _L, void _p);

例子一 light userdata

  1. #include <stdio.h>
  2. #include <string>
  3. #include <iostream>
  4. using namespace std;
  5. extern "C" {
  6. #include "lua.h"
  7. #include "lualib.h"
  8. #include "lauxlib.h"
  9. }
  10. typedef struct
  11. {
  12. int x;
  13. int y;
  14. int z;
  15. }TData;
  16. static int getAttribute(lua_State* L)
  17. {
  18. TData *data = (TData*)lua_touserdata(L, 1);
  19. std::string attribute = luaL_checkstring(L, 2);
  20. int result = 0;
  21. if (attribute == "x")
  22. {
  23. result = data->x;
  24. }
  25. else if (attribute == "y")
  26. {
  27. result = data->y;
  28. }
  29. else
  30. {
  31. result = data->z;
  32. }
  33. lua_pushnumber(L, result);
  34. return 1;
  35. }
  36. static luaL_Reg dataLib[] = {
  37. { "__index", getAttribute },
  38. { NULL, NULL }
  39. };
  40. void getMetaTable(lua_State* L, luaL_Reg* methods)
  41. {
  42. lua_pushlightuserdata(L, methods);
  43. lua_gettable(L, LUA_REGISTRYINDEX);
  44. if (lua_isnil(L, -1)) {
  45. /* not found */
  46. lua_pop(L, 1);
  47. lua_newtable(L);
  48. luaL_setfuncs(L, methods, 0);
  49. lua_pushlightuserdata(L, methods);
  50. lua_pushvalue(L, -2);
  51. lua_settable(L, LUA_REGISTRYINDEX);
  52. }
  53. }
  54. int main()
  55. {
  56. const char* filename = "test.lua";
  57. lua_State *lua = luaL_newstate();
  58. if (lua == NULL)
  59. {
  60. fprintf(stderr, "open lua failed");
  61. return -1;
  62. }
  63. luaL_openlibs(lua);
  64. TData input = { 123, 231, 321 };
  65. lua_pushlightuserdata(lua, &input);
  66. getMetaTable(lua, dataLib);
  67. lua_setmetatable(lua, -2);
  68. lua_setglobal(lua, "input");
  69. if (luaL_dofile(lua, filename))
  70. {
  71. //luaL_error(lua, "load file %s failed", filename);
  72. }
  73. lua_getglobal(lua, "data");
  74. int output = lua_tointeger(lua, -1);
  75. std::cout << output << std::endl;
  76. return 0;
  77. }

lua文件

data = input.x;
print(data)

例子二 full userdata

//#include <string.h>  

extern "C" {
    #include "lua.h"  
    #include "lauxlib.h"  
    #include "lualib.h"  
}

#include <iostream>  
using namespace std;

static struct StudentTag
{
    char *strName; // 学生姓名
    char *strNum; // 学号
    int iSex; // 学生性别
    int iAge; // 学生年龄
}T;

static int Student(lua_State *L)
{
    size_t iBytes = sizeof(struct StudentTag);
    struct StudentTag *pStudent;
    pStudent = (struct StudentTag *)lua_newuserdata(L, iBytes);

     //设置元表
    luaL_getmetatable(L, "Student");
    lua_setmetatable(L, -2);

    //lua_pushnumber(L, 123);

    return 1; // 新的userdata已经在栈上了
}

static int GetName(lua_State *L)
{
    struct StudentTag *pStudent = (struct StudentTag *)luaL_checkudata(L, 1, "Student");
    lua_pushstring(L, pStudent->strName);
    return 1;
}

static int SetName(lua_State *L)
{
    // 第一个参数是userdata
    struct StudentTag *pStudent = (struct StudentTag *)luaL_checkudata(L, 1, "Student");

    // 第二个参数是一个字符串
    const char *pName = luaL_checkstring(L, 2);
    luaL_argcheck(L, pName != NULL && pName != "", 2, "Wrong Parameter");

    pStudent->strName =(char*) pName;
    return 0;
}

static int GetAge(lua_State *L)
{
    struct StudentTag *pStudent = (struct StudentTag *)luaL_checkudata(L, 1, "Student");
    lua_pushinteger(L, pStudent->iAge);
    return 1;
}

static int SetAge(lua_State *L)
{
    struct StudentTag *pStudent = (struct StudentTag *)luaL_checkudata(L, 1, "Student");

    int iAge = luaL_checkinteger(L, 2);
    luaL_argcheck(L, iAge >= 6 && iAge <= 100, 2, "Wrong Parameter");
    pStudent->iAge = iAge;
    return 0;
}

static int GetSex(lua_State *L)
{
    // 这里由你来补充
    return 1;
}

static int SetSex(lua_State *L)
{
    // 这里由你来补充
    return 0;
}

static int GetNum(lua_State *L)
{
    // 这里由你来补充
    return 1;
}

static int SetNum(lua_State *L)
{
    // 这里由你来补充
    return 0;
}

static  luaL_Reg arrayFunc_meta[] =
{
    { "getName", GetName },
    { "setName", SetName },
    { "getAge", GetAge },
    { "setAge", SetAge },
    { "getSex", GetSex },
    { "setSex", SetSex },
    { "getNum", GetNum },
    { "setNum", SetNum },
    { NULL, NULL }
};

static luaL_Reg arrayFunc[] =
{
    { "new", Student},
    { NULL, NULL }
};

extern "C"  _declspec(dllexport) int luaopen_mytestlib(lua_State *L)
{
    // 创建一个新的元表
    luaL_newmetatable(L, "Student");
    // 元表.__index = 元表
    lua_pushvalue(L, -1);
    lua_setfield(L, -2, "__index");
    luaL_setfuncs(L, arrayFunc_meta, 0);
    luaL_newlib(L, arrayFunc);
    lua_pushvalue(L, -1);
    lua_setglobal(L, "Sdudent"); /* the module name */
    return 1;
}

lua 文件

require "mytestlib"

local objStudent = Sdudent.new()

objStudent:setName("果冻")
local strName = objStudent:getName()
print(strName )

for k,v in pairs(getmetatable(objStudent)) do
    print(tostring(k),tostring(v))
end

参考

http://blog.csdn.net/mydriverc2/article/details/51007803
http://blog.csdn.net/rain_qingtian/article/details/44781183