我如何在Lua-C API 5.2中创建一个类对象?

我正在使用Lua-C API为Lua 5.2包装C函数:

当我运行这个Lua:

...我看到这个输出(有错误):

我做错了什么?

点赞
用户6277151
用户6277151

好的,搞定了。我不得不在 Foo 的新元表中添加 __index__metatable,具体如下所示:

void register_foo_class(lua_State* L) {
  int lib_id, meta_id;

  /* newclass = {} */
  lua_createtable(L, 0, 0);
  lib_id = lua_gettop(L);

  /* metatable = {} */
  luaL_newmetatable(L, "Foo");
  meta_id = lua_gettop(L);
  luaL_setfuncs(L, _meta, 0);

  /* metatable.__index = _methods */
  luaL_newlib(L, _methods);
  lua_setfield(L, meta_id, "__index");

  /* metatable.__metatable = _meta */
  luaL_newlib(L, _meta);
  lua_setfield(L, meta_id, "__metatable");

  /* class.__metatable = metatable */
  lua_setmetatable(L, lib_id);

  /* _G["Foo"] = newclass */
  lua_setglobal(L, "Foo");
}
2012-06-25 20:57:57
用户1530347
用户1530347

我尝试回复你的解决方案,但显然我还没有足够的声望来这样做,所以这里有一个单独的答案。

你的解决方案很不错,但它不允许我想要做的事情:既有对对象的“类数组”访问,还可以在对象上使用函数。看一下这段 Lua 代码:

Foo = {}

mt = {
__index = function(table, key)
  print("Accessing array index ", tostring(key), "\n")
  return 42
end
}
setmetatable(Foo, mt)

Foo.bar = function()
  return 43
end

print(tostring(Foo[13]), "\n")
print(tostring(Foo.bar()), "\n")

--[[
Output:
Accessing array index 13
42
43
]]--

使用你的解决方案注册类似乎不允许这样做,因为 __index 条目被覆盖了。 也许在一个类上既有数组访问又有函数访问并不是很有意义,但为了简单起见(提供一种 C 函数用于注册两种类型的类),我想在任何地方使用相同的代码。有没有人有想法如何绕过这个限制,以便我可以从 C 创建一个既有 Foo.bar() 函数又有 Foo[13] 的类呢?

2012-07-17 00:40:23
用户2532220
用户2532220

下面是我如何满足你们两个的标准,以及j_schultz的:

#include <lua.h>
#include <lauxlib.h>
#include <stdlib.h>
#include <stdio.h>

#define LUA_FOO "Foo"

typedef struct {
    int x;
} Foo;

static int foo_gc(lua_State *L) {
    printf("## __gc\n");
    Foo *foo = *(Foo**)luaL_checkudata(L, 1, LUA_FOO);
    free(foo);
    return 0;
}

static int foo_doSomething(lua_State *L) {
    printf("## doSomething\n");
    Foo *foo = *(Foo**)luaL_checkudata(L, 1, LUA_FOO);
    lua_pushinteger(L, foo->x);
    return 1;
}

static int foo_new(lua_State* L) {
    printf("## new\n");
    Foo *foo = malloc(sizeof(Foo));
    int i = 1 + lua_istable(L, 1);
    foo->x = !lua_isnoneornil(L, i) ? luaL_checkinteger(L, i) : 0;
    *(Foo**)lua_newuserdata(L, sizeof(Foo*)) = foo;
    luaL_setmetatable(L, LUA_FOO);
    return 1;
}

static int foo_index(lua_State *L) {
    printf("## index\n");
    int i = luaL_checkinteger(L, 2);
    lua_pushinteger(L, i);
    return 1;
}

int luaopen_foo(lua_State *L) {
    // instance functions
    static const luaL_Reg meta[] =
    {   { "__gc"        ,foo_gc          },
        { NULL          ,NULL            }  };
    static const luaL_Reg meth[] =
    {   { "doSomething" ,foo_doSomething },
        { NULL          ,NULL            }  };
    luaL_newmetatable(L, LUA_FOO);
    luaL_setfuncs    (L, meta, 0);
    luaL_newlib      (L, meth);
    lua_setfield     (L, -2, "__index");
    lua_pop          (L, 1);

    // static functions
    static const luaL_Reg static_meta[] =
    {   { "__index" ,foo_index },
        { "__call"  ,foo_new   },
        { NULL      ,NULL      }  };
    static const luaL_Reg static_meth[] =
    {   { "new"     ,foo_new   },
        { NULL      ,NULL      }  };
    luaL_newlib      (L, static_meth);
    luaL_newlib      (L, static_meta);
    lua_setmetatable (L, -2);
    return 1;
}

Lua 代码:

local Foo = require('foo')
local foo = Foo.new(12)
local bar = Foo(24)

print(Foo[13])
print(foo:doSomething())
print(bar:doSomething())

Lua 输出:

## new
## new
## index
13
## doSomething
12
## doSomething
24
## __gc
## __gc
2021-12-07 00:36:57