Subject: Re: [ruby-ffi] Struct/ManagedStruct and GC behaviour |
From: Thomas E Enebo |
Date: 12/21/09 5:32 PM |
To: ruby-ffi@googlegroups.com |
On Mon, Dec 21, 2009 at 4:20 PM, Wayne Meissner <wmeissner@gmail.com> wrote:
<tom.enebo@gmail.com>:2009/12/22 Thomas E EneboI have been wondering about the Struct API myself. It seems like it should support a simple explicit memory management API ala: class MyFFIStruct < FFI::Struct .... MyFFIStruct.new do|struct_instance|
some_ffi_call struct_instance # Do other stuff.... end # I know the block has disposed of my allocated structIt does support this indirectly via MemoryPointer.new e.g. MemoryPointer.new(MyFFIStruct.size) do|p|
s = MyFFIStruct.new(p) some_ffi_call s # do other stuff end An alternative is to use FFI::Buffer as the backing memory - on JRuby, that is jvm-heap memory, which is copied in/out of a temporary native memory area (usually on the stack) when passed to a native function. For small structs, especially ones that are passed to a native function just once, this can be up to 10x faster than the alloc/free cycle of a MemoryPointer backed Struct.
Thanks for the additional info and the code snippet for explicit management. Personally, I think that an explicit API like this should be the norm since there are no guarantees on when GC happens and in my experience it is much longer than most people expect. I think too many people believe in magic and the only way to combat it is to make the implicit stuff be more typing (or the explicit stuff less typing). I will probably make a class method in Struct which allows something like: MyFFStruct.create do|struct|
... end Under the covers it will do what you demonstrated above: def self.create(&block) MemoryPointer.new(size) {|p|
block.call new(p) } end Or something like this... -Tom-- blog: http://blog.enebo.com twitter: tom_enebo mail: tom.enebo@gmail.com