大话C与Lua(五) 面向对象的数据结构——userdata

如何实现面向对象?

熟悉Lua的同学都知道!在Lua内部已经实现了面向对象的基本机制(table), 同时也为宿主语言(在这里是C语言)提供了一套接口来实现自定义数据结构(userdata)。在此,我们可以简单的利用metatable与__index的访问机制,为userdata实现一套简单的面向对象的访问方式。

stu.c

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

typedef struct _Student
{
    const char * strName ; // 学生姓名
    int strNum ; // 学号
    int iSex ; // 学生性别
    int iAge ; // 学生年龄
}Student;

int lnew(lua_State* L){
    Student *stu =  lua_newuserdata(L,sizeof(Student));
    if(NULL == stu){
        return 0;
    }
    luaL_setmetatable(L,"stu");
    return 1;
}

int lset(lua_State* L){
    Student *stu = luaL_checkudata(L,1,"stu");
    stu->strName = luaL_checkstring(L,2);
    stu->strNum = luaL_checkinteger(L,3);
    stu->iSex = luaL_checkinteger(L,4);
    stu->iAge = luaL_checkinteger(L,5);
    return 0;
}

int lget(lua_State* L){
    Student *stu = luaL_checkudata(L,1,"stu");
    lua_pushstring(L,stu->strName);
    lua_pushinteger(L,stu->strNum);
    lua_pushinteger(L,stu->iSex);
    lua_pushinteger(L,stu->iAge);
    return 4;
}

const luaL_Reg mylib[] = {
    {"new",lnew},
    {"set",lset},
    {"get",lget},
    {NULL,NULL}
};

LUA_API int luaopen_stu(lua_State* L){
    luaL_newmetatable(L,"stu");
    lua_pushstring (L,"__index");
    lua_pushvalue(L,-2);
    lua_rawset(L,-3);
    luaL_setfuncs(L,mylib,0);

    luaL_newlib(L,mylib);
    return 1;
}

main.lua

local stu = require "stu"
local stu = stu.new()
print(stu)
stu:set("Candy",1024,1,26)
local name,id,sex,age = stu:get()
print(name,id,sex,age)

运行结果:

[root@localhost ~]# cc -o stu.so stu.c  -Wall -O2 -fPIC -shared 
[root@localhost ~]# lua main.lua 
stu: 0x19380d8
Candy   1024    1   26
[root@localhost ~]# 

运行结果很简单。现在,我们简要分析一下具体实现步奏。

首先我们在注册表创建了一个metatable,并且起名”stu”。然后为这个元表添加一个__index元方法,然后将自身作为键值查找域。最后使用setfuncs为元表注入方法。

上述步奏等效于lua中如下操作:

local meta = {1,2,3}
local t = setmetatable({},{__index=meta})
print(t[1])

这里需要注意的是:

  • full-userdata的生命周期是由Lua来管理的。</td>
  • 如果由Lua gc回收了userdata的使用空间,C语言还引用原地址将会引起段错误。
  • 所以如果需要完全使用C API来管理 userdata是生命周期,请使用light userdata。
    原文作者:水果糖的小铺子
    原文地址: https://www.jianshu.com/p/6c52a764c074
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞