The question is how can I use both methods and properties.
In a broad sense, methods are simply properties that are solved for functions.
If I just add __index to the funset RegisterClass array, it is never called.
This is a real problem, isn't it? The rest of your message is distracted from the real problem.
According to the docs, luaL_newlib creates a new table . So luaL_newmetatable. You create two tables in RegisterClass, which makes no sense. You only need to create the meta meta, and it is the meta meta that you need to add the __index and __newindex .
You cannot have __index just specify the funcs table (a shortcut for implementing class methods), and not if you want to manually march data to and from C ++ class instance properties. This should be a function that distinguishes access to the method (the value refers to the scope of the class) and access to properties (the value comes from the scope of the instance).
Here is an example of how your method / property access will work in Lua. The specifics are different using API C, but the approach will be the same:
-- This is the metatable you create in RegisterClass for the C++ class 'Foo' Foo = { } -- This is pretty close to how your __index metamethod would work in the C++ code, -- except you're going to have to write code that resolves which field on the C++ object -- corresponds to 'key', if any, and push that onto the stack. function Foo.__index(instance,key) local method = rawget(Foo,key) if method then return method end return instance.properties[key] end -- This is pretty close, too, except that if you want users to be able to add properties to the Lua object -- that coexist with the C++ object properties, you'll need to write the value to the right place. function Foo.__newindex(instance,key,value) instance.properties[key] = value end -- this doesn't have to be a method on the metatable function Foo:new(state) return setmetatable({ properties = state}, self) end -- example of a class method function Foo:dump() print('dump:', self.x, self.y) end -- simulation of the userdata, an instance of your C++ class cppClassInstance = { x = 10, y = 20, } obj = Foo:new(cppClassInstance) print(obj.x) -- read `x`, which is resolved to cppClassInstance.x obj.x = 5150 -- write to 'x', which writes to cppClassInstance.x print(obj.x) -- witness our change obj:dump() -- call a class method