Lua 中使用 C 语言的用户自定义类型——userdata

零、前言

经过之前的文章分享,我们已经知道如何通过扩展函数来扩展 Lua 。但这里涉及到一个问题,Lua 脚本中如何使用 C/C++ 中的类型,如何像操作对象一样操作 C/C++ 类型的实例。解决这一问题就需要用到 userdata 类型(用户数据类型)。

userdata 类型,分为两种:

  1. 完全用户数据(full userdata)
  2. 轻量级用户数据(light userdata)

一、full userdata(完全用户数据)

full userdata 为 Lua 语言提供了可以用来存储任何数据的原始内存区域,没有预定义的操作。 使用完全用户数据的 C-API 为:lua_newuserdata

使用 full userdata 创建的内存不需要进行释放,Lua 会进行管理和释放。 而如果 full userdata 关联的对象需要释放,可以通过给 full userdata 设置元表,元表中设置 __gc 进行监听释放,调用关联的对象的释放方法进行释放,下面的第五小节会进行展示这一过程。

1、lua_newuserdata

#define lua_newuserdata(L,s)	lua_newuserdatauv(L,s,1)

描述:

分配一块指定大小的内存,然后将该内存以 userdata 的类型进行压栈,并返回该内存的指针。

参数:

  • 参数 L: Lua 状态的指针。
  • 参数 size: 要分配的 userdata 对象的字节大小。

返回值:

返回指向该内存的指针,可以通过这个指针进行对象的操作。

2、举个例子

假设我们需要向 Lua 暴露一个 C++ 的类型:User ,在 Lua 脚本中可以创建该类型,并且调用该类型的方法。

第一步,定义一个 User 类。

class User {
   
private:
    std::string name;
    long long age;
public:
    std::string introduce() {
   
        std::stringstream info;
        info << "大家好。我叫" << name << "。今年" << age << "岁。请关注我。";
        return info.str();
    }

    void setName(std::string name) {
   
        this->name = std::move(name);
    }

    void setAge(long long age) {
   
        this->age = age;
    }

    std::string getName() {
   
        return this->name;
    }

    long long getAge() {
   
        return this->age;
    }
};

第二步,定义对 User 操作相关的方法,并将这些方法用作库方法,向 Lua 暴露一个 user 库,可以通过该库创建 User 类型的 full userdata ,并操作背后真正 C++ 实例。

static int newUser(lua_State *L) {
   
    std::string name = luaL_checkstring(L, 1);
    long long age = luaL_checkinteger(L, 2);

    // 生成一个 User Data 并压入栈中
    auto *user = (User *) lua_newuserdata(L, sizeof(User));
    user->setName(std::string(name));
    user->setAge(age);

    return 1;
}

static int introduce(lua_State *L) {
   
    User *user = (User *) lua_touserdata(L, 1);
    lua_pushstring(L, user->introduce().c_str());
    return 1;
}

static int setName(lua_State *L) {
   
    User *user = (User *) lua_touserdata(L, 1);
    std::string name = luaL_checkstring(L, 2);
    user->setName(std::string(name));
    return 0;
}

static int setAge(lua_State *L) {
   
    User *user = (User *) lua_touserdata(L, 1);
    long long age = luaL_checkinteger(L, 2);
    user->setAge(age);
    retu
  • 14
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值