lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I have a C++ Reflection library that reflects functions, classes, events, etc. and allows you to query them by name at runtime and pass arbitrary parameters. I want to use this library to bind my C++ code to LUA.

This allows me to specify a single C function that translates the incoming LUA stack to the Reflection stack, for all lua_register calls. Of course, this still means the LUA tables will replicate all the symbol names already stored in the Reflection database, which is something I've set out to avoid.

To start with I need to get around the problem of telling, from within a C function, the name of the C function just called. Other than the Debug API I can't see any means of getting at that, and I don't want to use the Debug API. So instead I initialise my LUA State with the following script:

	# Create function 'class'
	Function = {}

# Create metatable that redirects name lookups to Function and, when called passes the function name as the first parameter Function_mt = { __index = Function, __call = function (f, ...) return f.func(, unpack(arg)) end }

	# Named 'constructor'
	function Function:new(name, func)
	   return setmetatable( { name = name, func = func }, Function_mt)

If I use this in place of a function type then I always get the function name as the first parameter. So the first question is, would this be the best way to achieve something like this?

Next, I build another metatable for the global environment:

	# Create metatable that creates Function 'objects' when looking up names
mt = { __index = function(t, key) return Function:new(key, CallReflectionFunction) end }

	# Assign metatable to the global environment
	setmetatable(_G, mt)

The resulting C++ side of this is pretty minimal, which I'm really liking. I just have to register the CallReflectionFunction. The purpose of this function is to read the first parameter and lookup the function by name. Then translate each LUA stack parameter into the Reflection stack and then execute the function, returning any values.

So the final question is, are there any better ways of achieving this? Is modifying the metatable of the global environment even a good idea?

I want to extend this idea to work with namespaces and classes next so I'd be grateful for any input.

- Don