lua-users home
lua-l archive

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

Hi List,

Recently I've been experimenting with Fabio Mascarenhas' excellent FFI library
Alien (version 0.5.0). It is very useful, but I found myself writing quite a
few notes about things as they came up, and thought I'd post them to the list.
I'd be interested to know whether other Alien users have hit the same things,
and if so, how they sorted them out.

* It's often valid to pass NULL for a callback, so allowing nil for function
  parameters or struct fields of type 'callback' would be very useful, but
  currently it causes an error:
   setcallback = alien.mylib.setcallback
   setcallback:types("void", "callback")

   setcallback(nil)    --> ERROR: bad argument #1 to 'setcallback'
                           (alien function or callback expected)
* Various 'ref' types are missing - 'ref pointer' in particular has come up
  a lot for me, but also occasionally 'ref float' etc.
* Using alien.get(1, 'char') returns a signed value, which seems inconsistent
  with all other use of 'char' where it is unsigned ('byte' is offered as
  the signed alternative, so I assume 'char' *is* meant to be unsigned):
   b = alien.buffer(1)
   b:set(1, 255, 'char')

   print( b:get(1, 'char') )     --> -1
* Is there any way to be able to pass a FILE* pointer inside a Lua file object
  to an Alien function?

These are issues that I know how to get around, but still get caught out by

* If you assign an Alien callback to a field in a struct, it is not "pinned",
  and can easily be accidentally left eligible for garbage collection:
   mystruct_def = alien.defstruct{
    {"mycallback", "callback"}

   mystruct = mystruct_def:new()
   function myfunction()
     print("Hello World")
   mystruct.mycallback = alien.callback(myfunction, {ret="void"})

   collectgarbage() --> 'mycallback' gets garbage collected
* Forgetting to pass any second parameter to alien.callback() causes the
  application to crash completely, rather than raising a normal error.

Finally, these are some subjective comments about the way Alien works:

* Using alien.buffer() on a light userdata works by changing the global
  metatable for light userdata and returning it. This mainly isn't a problem -
  though it does keep catching me out when I print() a light userdata for
  debugging purposes and it tries to print arbitrary data - but it feels kind
  of fragile and "unclean".
* It seems odd that if you want to get the pointer for a struct you should
  call it like a function, but to get the pointer for an array you access
  array.buffer. I find it way too easy to do the wrong one or forget to do
  either. Could it be based on a __topointer() metamethod instead?
* I am not convinced it was a good idea to use 1-based offset parameters in
  buffer:get(...) and buffer:set(...). I know that it might seem best to
  remain consistent with Lua's 1-based indexing of strings and tables, but
  my argument would be that there's a difference between an index and an
  offset - while it may make sense to index from 1 (even if some folk don't
  exactly care for it) it really *doesn't* make sense to offset from 1.
  This difference is actually recognised in Lua's own standard libraries -
  cf. the offset parameter of the file:seek() method.