[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Please comment on these Lua to C library bindings that I wrote
- From: Jerome Vuarand <jerome.vuarand@...>
- Date: Tue, 20 Nov 2012 10:54:53 +0000
2012/11/20 Richard W.M. Jones <rjones@redhat.com>:
> My bindings:
> http://oirase.annexia.org/tmp/lua-guestfs.c.txt
>
> There are some examples of using them here:
> http://libguestfs.org/guestfs-lua.3.html
> https://github.com/libguestfs/libguestfs/tree/master/lua/tests
>
> The bindings are generated by a custom script, hence their length.
> You can ignore everything between 'lua_guestfs_add_cdrom' and
> 'lua_guestfs_zgrepi', which is about 90% of the file, on a first pass.
>
> In general, it all seems to work.
>
> However I've had some specific problems:
>
> - How do you pass and return 64 bit ints? (which must work with full
> 64 bit precision even on 32 bit platforms)
If you can do with only 53 bits, you can use plain Lua numbers. For
file offsets (with byte-size words) for example that covers 8
petabytes. Otherwise you have to revert to the same techniques as in
C, pass the number in two parts in a table, or as an opaque value (in
a string or in a userdata) which limits the manipulation the user can
apply, but depending on the situation that may be acceptable.
> - Is the way I've done callbacks safe? Particularly stashing the
> lua_State pointer in a C struct for potentially a long time.
> [see lua_guestfs_set_event_callback, event_callback_wrapper]
It all depends on the threading model of the library you're binding.
You should ensure that your callbacks are called in order and don't
overlap, as the Lua interpreter cannot be used simultaneously by
several threads. For some libraries (FUSE for example) that's an init
option.
>
> - How do I push a userdata onto the Lua stack? Instead I'm pushing
> a pointer to a userdata using: lua_pushlightuserdata (L, u);
> [see event_callback_wrapper]
If you only have a pointer to the userdata you can't push it back. You
need an actual Lua reference, either on the stack, in an upvalue or in
a table. If you only want to keep the pointer around, you can create a
mapping table in the registry, so that you can get back a reference
from the pointer. Make that mapping table a weak-valued table, use the
pointers (pushed as light userdata) as keys and the full userdata as
values.
> - How do you print "any" type, from C?
There's no built-in framework for that, because for non-basic types
there is no trivial way to do it. There are plenty of libraries
around, in Lua or in C (keep in mind that if you got a lua_State
pointer you can call Lua code from C very easily).
> - This works:
> luaL_register (L, NULL, handle_methods);
> but this fails:
> luaL_register (L, "guestfs", handle_methods);
> Why?
That by itself should work. How do you determine it doesn't? Do you
get an error?
> - Are the bindings GC-safe? For example, I often get strings, arrays
> of strings using 'luaL_checkstring', and I'm doing stack operations
> at the same time. Could the strings get moved (or freed) between me
> getting the pointer and me passing the pointer to the C function?
> [see get_string_list for one example]
It's only safe as long as the string objects are referenced (by the
stack or any other reference). The get_string_list function itself is
OK, but its return value is valid only as long as the table it's
wrapping is referenced. Otherwise it may get collected and the
pointers in the returned array would get invalid.
This is unrelated to your question, but I noticed that that
get_string_list function uses malloc, which requires the caller to
call free. Note that you can use lua_newuserdata instead of malloc to
push temporary memory blocs on the Lua stack. They will automatically
be collected when you give back control to Lua (return from your
lua_CFunction). The nice bit is that it lets you call functions that
could throw Lua errors without worrying about potential leaks (right
now if a Lua error gets thrown between "get_string_list" and the
corresponding "free" call, the array of pointers is lost).