Void Pointer Handling

Many library functions accept an opaque "void*" argument which is passed as-is to a callback also provided by the user. For example, you could do the following (from examples/clock.lua):

lbl = gtk.label_new "" onTimeoutClosure = gnome.closure(onTimeout) timer = glib.timeout_add(1000, onTimeoutClosure, lbl)

In this case, an object (GtkLabel) is given for the void* argument. This needs no special handling, but you must make sure that the object is not freed, so the following code, appended to the one above, leads to problems:

lbl = nil collectgarbage "collect"

Following Lua types can be converted to a void* argument by the function lua2ffi_void_ptr (in src/voidptr.c):

Void* Wrapper

As mentioned in the list above, a "void* wrapper" exists to handle arbitrary Lua values. The library must be given a void* pointer which must continue to be valid while it is used, and should be freed afterwards. When accessing such a void*, for example as an argument to a callback, or as an element of a structure, it must be possible to retrieve its value or free the value.

Therefore, a void* wrapper consists of three interdependent entities:

Structure Diagram
  1. Zero or more Lua userdatas (Lua Wrappers) with a pointer to the C structure. This is what the programs "see" and work with. It has a metatable to allow several methods of accessing the data.
  2. A C structure (the void* wrapper) with a reference to the Lua value and a reference counter, which counts how many Lua Wrappers exist for it. This counter should be at least one, and is updated when Lua Wrappers are created and garbage collected. When it drops to zero, the void* wrapper is automatically freed.
  3. An arbitrary Lua value, like a string, a table etc. A reference is created through the luaL_ref mechanism and stored in the void* wrapper.

For example, a "GTree" (of GLib) stores pairs of void* (key and value). A complete example can be found in tests/027-closure.lua. The important parts of this example are given below:

function destroy_it(wrapper) wrapper:destroy() end cl = { gnome.closure(compare_func), gnome.closure(destroy_it) } t = glib.tree_new_full(cl[1], nil, cl[2], cl[2]) t._closures = cl cl = nil t:insert("hello", "world") t:insert("another key", { 2, 3, 4, "another value" }) t:destroy()

When you remove an item, or call :destroy on the tree (which removes all items), the "destroy_it" function is called for both key and value; it receives a Lua representation of the wrapper and not the wrapped object. This allows to call the destroy method on it, or use its value. This Lua userdata forwards __len, __index and __newindex to the wrapped Lua value, which is useful if it's a table, for example.

Note When you need to pass a Lua value to a function that expects a GValue, like gtk_tree_model_set_value, you need to use a Boxed Value.

The Wrapper Object

The wrapper object, which is the top box in the diagram above, is a Lua userdata that allows to access the Lua value (bottom box in the diagram). It offers the following methods:

.value
When accessing wrapper.value, the Lua value is returned.
:destroy()
Calling this method decreases the reference count of the void* wrapper.
.anything, [n]
For any other index of any type (numeric, string, ...), this index request is passed to the wrapped Lua value. This works if this Lua value is a table or userdata.

Note that if you want to access a field named "value" or "destroy" in the wrapped Lua object, you have to use wrapper.value.value or wrapper.value.destroy instead. If you use a variable as index, be on the safe side and use wrapper.value[index].

Functions

gnome.void_ptr(value)

Create a void* wrapper for the given value, and return a Lua object representing it. The wrapper's reference counter is set to one, so that when the Lua object is freed, the void* wrapper is also released.

any_function(value)

If the argument type of value is "void*" (or simliar, like gpointer), and value is not already a void* wrapper, then a void* wrapper is automatically created for it. Its reference counter is also set to one, but no Lua object is created. So it will not be freed automatically, but you have to do that manually by calling the :destroy() method on the void* wrapper.

Debugging

As you can see, memory management is not automatic for void* wrappers. Lua-Gnome can't infer automatically when such a void* wrapper is not needed anymore, unless specialized handlers are written for individual classes. To aid finding memory leaks, two functions are provided:

gnome.get_vwrappers_count()

Returns three integers: the number of currently existing void* wrappers, how many were allocated in total (can be less than the first number if some have already been freed), and finally the number of currently existing Lua representations of void* wrappers; this is only for information as these are garbage collected automatically by Lua.

gnome.dump_vwrappers()

Show the information of the above function, and show a list of currently existing void* wrappers; each with memory address, followed by the source file and line number where it was allocated.

Source

For implementation details, see src/voidptr.c.