lua-users home
lua-l archive

Re: C binding strategy

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


On 8/14/2012 7:26 AM, Francisco Tolmasky wrote:
There are a few "small" object types that I need to occasionally
pass over to the C side of things. For example, lets say a Point
class (containing x and y). These points get used internally by the
C code to do graphics stuff, etc (or say Quaternions, etc.). The
point is, I'm referring to simple objects that you might use a struct
for, would rarely have a pointer for in C or a non-trivial lifetime
like an "Image" class or something. I've devised two strategies:
1. Create a traditional userdata-style object that I expose to Lua.
This is what we did. I added Lua to an existing project, which already had a way of passing data (based on a reference-counted boost::any, but modified considerably to speed things up). The idea was that data could travel freely from Lua to C++ and back, without it being copied more often than strictly neccesary. Together with some template- and macro glue this makes for bindings that are relatively easy to write (and read). For example, the C function handling the __add metamethod of our Point-class just reads
 int Add(lua_State *L)
 {
 // Can only add two CEPoints.
 // ELuaBindings::ToCEPoint() will raise luaL_error if the
 // arguments are of the wrong type.
 const CEPoint *a = ELuaBindings::ToCEPoint(L, 1);
 const CEPoint *b = ELuaBindings::ToCEPoint(L, 2);
 CEPoint *result = ELuaBindings::PushNewCEPoint(L);
 *result = *a + *b;
 return 1;
 }
The overhead in terms of "amount of boilerplate code" is limited, the actual *runtime* overhead is acceptable, but what causes some concern is memory usage. The userdata only contains a refcounted pointer, irregardless of the size of the data pointed at by that pointer. Simply put, the garbage collection fails to realise that there is a difference between a "Point" and an "Image", and only "sees" the memory burden of the pointer. It simply doesn't realise that the memory footprint of a userdata may be bigger than the size of the userdata itself, and when left to its own devices will quickly cause memory to run out - even though the memory 'consumed' by the lua state will remain low. So far, the only way we found around this is to manually call the garbage collection on a (very) frequent basis. However, this causes a significant additional runtime; it is not uncommon to see the garbage collection take more time than the actual payload.
Kind regards,
Martijn

AltStyle によって変換されたページ (->オリジナル) /