swig/swig — pull request #189 by v-for-vandal (2014-06-07 14:21:52+00:00)
Title: RFC: lua metaclass library.

Hi @wsfulton. This request is a response to "[Swig-devel] Lua: Hooking Swig" thread.
I wanted to hide internal structure of SWIG-lua wrappers behind some API. For that, a new "library" (of sort) was created - luametaclass. It is currently resides in Examples/lua/metaclass because I couldn't find a proper way to integrate it with SWIG. Could you please give me some guidance in this matter ? It is mostly administrative issues - where to put, when to build etc.

# General library description:
Library itself is a SWIG interface file: luametaclass.i. It must be processed with SWIG and then compiled into library. Code is C89-compatible. It provides one structure - SWIG_Lua_metaclass (structure will be renamed to something not so mouthful later). Structure is %extend'ed with methods that supports adding/removing functions and adding/removing member variables. It is a bare minimum that metaclass library should provide.
With this library it is possible to edit classes in runtime - adding hooks or just adding methods that are not easily expressed with SWIG.

## Accompanying changes:
1. The requested replacement of lua_iscfunction with lua_isfunction.
2. New feature was introduced - %feature("unlimited_args"). This feature is meaningful only for functions with lua_State* as input. Such functions solve the problem with "number of arguments" checks. (also mentions in some thread in swig-devel) Example:
```
int my_function_with_many_args( int first_arg, double second_arg, lua_State *L )
```
Swig-genrated wrapper will check that number of arguments is exactly 2 (typemap for lua_State has numinputs=0). But that's not true. The idea of this function is to have 2 definite arguments and then some unknown at compile time number of arguments in lua stack.
More, this type of functions is the only way to write C functions working with Lua types, because lua doesn't provide any C structure corresponding to its tables/functions/etc.
```
int add_to_table_elemenets( int inc, lua_State *L ) {
assert(lua_istable(L,-1));
/* pseudo-code */
for key, value in do
[key] = value + inc
end
/* end of pseudo-code */
}
```
The real-life examples could be found in luametaclass.i ))
The implementation is somewhat not strict enough. I wasn't able to find a nice way to ensure that this feature could be placed only on functions with lua_State* argument. The only way I found is a deep function arguments introspection, and that seems like overkill to me.

## Questions&Issues
Could you please give me some advice regarding the following issues:
1. How should I integrate it with SWIG ? In general, I want to every user of SWIG-lua to be able to simply type in lua script
```lua
require(luametaclass)
```
and - voila - everything should work. But for that to happen library must be compiled during SWIG compilation.
Another options is to put it into Lib/lua as interface file, remove the %module directive from it and tell user to include it in every module with %include directive. But that would put a copy of library into every module. Plus it will add classes from the library right into module own lua-namespace. Instead of
```
require(my_module)
require(luametaclass)
MyClass_meta = luametaclass.SWIG_Lua_metaclass(my_module.MyClass)
```
one will have to write
```lua
require(my_module)
require(my_second_module)
MyClass_meta = my_module.SWIG_Lua_metaclass(my_module.MyClass)
MySecondClass_meta = my_second_module.SWIG_Lua_metaclass(my_second_module.MySecondClass)
```
That seems ... dirty.
2. SWIG_Lua_return_hack. It was the least dirty method to return correct number of arguments. If anyone can come up with some nice method, I will be more than happy to implement it.

# Tests
Attached .runme file serves as test.