How do I create a class object in Lua-C API 5.2?

lua

Solution

Ok, got it working. I had to add `__index` and `__metatable` to `Foo`'s new metatable, as shown below:

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");
}

Problem

I'm wrapping a C function with Lua, using the Lua-C API for Lua 5.2: ``` #include <lua.h> #include <lauxlib.h> #include <stdlib.h> #include <stdio.h> int foo_gc(); int foo_index(); int foo_newindex(); int foo_dosomething(); int foo_new(); struct foo { int x; }; static const luaL_Reg _meta[] = { {"__gc", foo_gc}, {"__index", foo_index}, {"__newindex", foo_newindex}, { NULL, NULL } }; static const luaL_Reg _methods[] = { {"new", foo_new}, {"dosomething", foo_dosomething}, { NULL, NULL } }; int foo_gc(lua_State* L) { printf("## __gc\n"); return 0; } int foo_newindex(lua_State* L) { printf("## __newindex\n"); return 0; } int foo_index(lua_State* L) { printf("## __index\n"); return 0; } int foo_dosomething(lua_State* L) { printf("## dosomething\n"); return 0; } int foo_new(lua_State* L) { printf("## new\n"); lua_newuserdata(L,sizeof(Foo)); luaL_getmetatable(L, "Foo"); lua_setmetatable(L, -2); return 1; } void register_foo_class(lua_State* L) { luaL_newlib(L, _methods); luaL_newmetatable(L, "Foo"); luaL_setfuncs(L, _meta, 0); lua_setmetatable(L, -2); lua_setglobal(L, "Foo"); } ``` When I run this Lua: ``` local foo = Foo.new() foo:dosomething() ``` ...I see this output (with error): ``` ## new ## __index Failed to run script: script.lua:2: attempt to call method 'dosomething' (a nil value) ``` What am I doing wrong?

Original source