C++/Lua FFI to render userdata as a table?

Viewed 323

I have the following simple code in C++ where Object is a std container:

static int create_an_object(lua_State* L) {
  auto obj = static_cast<Object*>(lua_newuserdata(L, sizeof(Object*)));
  *obj = another_valid_obj;

  luaL_newmetatable(L, "object_metatable");
  lua_pushcfunction(L, object_metatable_function);
  lua_setfield(L, -2, "__index");
  lua_pop(L, 1);
  return 1;
}

static int object_metatable_function(lua_State* L) {
  string index = luaL_checkstring(L, -1);
  if (index == "foo") {
    lua_pushnumber(L, 123);
  }
  // Handles other indices, or throws error.
}

lua_pushcfunction(L, create_an_object);
lua_setglobal(L, "create_an_object");

With the FFI above, I can achieve indexing of Object in Lua such as:

local obj = create_an_object()
print(obj.foo)   -- 123

Meanwhile print(obj) shows that obj is userdata: 0x12345678.

Is it possible to use some metamethod magic so that obj could be used as a table, while print(obj.foo) still prints 123? I am running my code in Lua 5.1.

1 Answers

I'm not exactly sure what you mean by "could be used as a table", but if you want to print something different from the default from print(obj), then you'll need to assign __tostring metamethod and return some string from it. This string may look like "userdata: 0x12345678 = {foo = 123}" if you want (or simply "{foo = 123}").

If you mean making it work as a table when assigning a new index to it, then __newindex metamethod should be used.

Related