Subject: Re: [ruby-ffi] Re: Initialize FFI::Pointer in C? |
From: Wayne Meissner |
Date: 12/9/09 2:29 PM |
To: ruby-ffi@googlegroups.com |
You can setup that callback all from ruby.
module Foo
callback :my_callback, [ :pointer ], :int
attach_function :DefineFunction, [ :string, :char, :my_callback, :string ]
end
Then you set it up like so:
cb = Proc.new do |p|
# Do whatever you want to do in the callback here
puts "pointer=#{p.inspect}"
# return zero to C code
0
end
Foo.DefineFunction("ruby-callback, "d".ord, cb, "RubyCallback")
You need to stash the 'cb' reference somewhere so it does not get
garbage collected until the callback is no longer needed, but that is
all the setup you should need to do to use that api from FFI.
2009/12/10 Simon Chiang <simon.a.chiang@gmail.com>:
<wmeiss...@gmail.com> wrote:The problem is that I need to register the C function with a codebase I don't control. I need to call a function like this in C: int RubyCallback(void *thing) {...} DefineFunction("ruby-callback", 'd', (int (*)(void)) RubyCallback, "RubyCallback"); The leading inputs are not important for the example but if you look at the latter arguments you can see I need both a pointer to the callback function and the name of the function. I think the FFI callback provides a function pointer but not a name, right? Is there a way I can name the callback? I'm ok with manually maintaining my calls to the C api. Do you have suggestions about how I can use it in this context? Thanks. ==== FYI This is the signature of the DefineFunction method. int DefineFunction(functionName,functionType, functionPointer,actualFunctionName); char *functionName, functionType, *actualFunctionName; int (*functionPointer)(); And if it helps, the version of the passing OS X is 10.5.8. On Dec 9, 12:04 am, Wayne Meissnerhttp://wiki.github.com/ffi/ffi/exampleshas a callback example, as doeshttp://wiki.github.com/ffi/ffi/windows-examples 2009/12/9 Simon Chiang <simon.a.chi...@gmail.com>:Really, don't use the C api - it will break at some point, since it is not intended in any way to be a public api. Use a FFI callback to call from C to ruby.I'm building a callback to ruby from an extension and I would like to pass back pointers much like an attached function that returns a :pointer. Basically something like this:
int RubyCallback(void *thing) { VALUE ffi_pointer = rbffi_Pointer_NewInstance(thing); VALUE ruby_module = rb_const_get(rb_cObject, rb_intern ("SomeModule")); VALUE ruby_result = rb_funcall(ruby_module, rb_intern("callback"), 1, ffi_pointer);
long result = FIX2INT(ruby_result); return(result); }
And then in ruby:
module SomeModule module_function
def callback(ptr) ptr.inspect # => shows this to be an FFI::Pointer end end
A method like this works on OS X with ffi-0.5.0 (pre snow-lepoard, I'll get the version if necessary) but results in a segfault on snow leopard 10.6.2. The segfault is triggered upon inspect. I don't know how FFI works... I really only got this working by taking a guess at what rbffi_Pointer_NewInstance does. Any ideas what's going wrong on 10.6.2 and/or how I can do this better?