Cosmin Apreutesei wrote: > The function bellow attempts to find the name of a constant in the > winapi namespace given a prefix and a value. I presume this is only used for debugging? Because this is rather slow. > It would be useful if cdata pointers would anchor their target if it's > a struct or array. In Lua an unreachable object can be safely > collected only because by definition it cannot affect any other > object. Why not extend this useful semantic to ffi pointers? I can see where you're coming from. But a core strength of the FFI is that the GC _never_ has to traverse cdata types. It never has to look for pointers or track ownership. In general, the GC cannot know whether a pointer needs to be followed or not. Ok, so one could remember that a certain pointer was originally derived from a collectable object. But what happens if you do p=p+42? Now you've got an interior pointer (which cannot be followed) and the original 'p' is gone. Does that still keep the GC object alive? What happens with x.foo = ffi.new(...); x.bar = ffi.C.malloc(...)? So the 'foo' pointer field needs to be followed, but the 'bar' field doesn't. How do you want to efficiently keep this info? Or what happens with p = ffi.C.strchr(str, 'x')? The str object presumably needs to be kept alive or 'p' may be a dangling pointer. There's no way the FFI can now that strchr() returns an interior pointer to an object passed as an argument. It's questions and inconsistencies like this, that make this approach unattractive. It's much more consistent to never traverse cdata objects and to shift the responsibility to keep GC objects alive to the programmer. After all, this is a low-level API to interface with C. > Plus this property is so much taken for granted > in Lua that it's easy to forget and write innocently looking code like > SNDMSG(hwnd, BCM_GETIDEALSIZE, 0, ffi.cast('SIZE*', ffi.new('SIZE', > size)))). Yes, I realize there are some GC pitfalls with the FFI. But that's kind of unavoidable if you mix manual memory management with a GC. [BTW: That example doesn't make sense, because one needs to get the returned button sizes from the struct _after_ the call returns. So you have to keep a reference to the GC object, anyway.] > In winapi there's tons of structs with short* buffers. In fbclient > (firebird's client library) there's even structs with pointers to > structs with pointers to arrays, all that you allocated yourself. I > have two options: a) cram all related structs and buffers in tables > and carry those around or b) use weak tables which gets me transparent > anchoring (weak tables are underrated :)). c) Allocate the outermost struct as a GC object, allocate all other data by calling malloc() and provide a __gc metamethod for the struct which calls free() on its members. Remember: You don't _have_ to use GC objects. They aren't even the best option if you have to do manual lifetime management, anyway. > 3) issue > ffi introspection (this has been asked before and probably answered, > but I'll give my reasons), especially struct fields (name & type). > > 3) story > Automatic testing (eg. code generation for unit tests stubs). > Debugging tools (eg. pretty-print a struct). Not sure if or when I'll add this. I'd like to keep this outside of the core VM. Yes, the info is all there, tightly packed inside some internal data structures. I can imagine a 'ffi.reflect' module, which accesses those internals (using the FFI itself!) and offers a nice API with type info, type iterators, field iterators and the like. [Alas, I don't have the time to design or implement this right now.] --Mike