From: Eric Hodel Date: 2009-11-24T08:18:04+09:00 Subject: Re: RubyInline - passing pointer from one function to another On Nov 20, 2009, at 06:26, Marcin Lewandowski wrote: > I'm trying to write ruby interface to JACK audio library. I've chosen > RubyInline due it's simplicity. What I want to achieve is to have ruby > code like this: > > client = JACK::Client.new "my_name" > puts client.get_sample_rate > > To achieve that I need to pass pointer to variable of jack_client_t* > from libjack from one function to another. What I tried to do is > available at http://pastebin.com/m3b6ee0c9 but as you can expect it > doesn't work. > > How can I do that? Is there any way to save pointer in instance of > ruby class e.g. in the same way as I can access strings? You'll need to use the Ruby/C API for this, namely Data_Wrap_Struct and Data_Get_Struct. Passing around the pointer as an instance variable (without even using INT2FIX/FIX2INT) can only lead to memory leaks and segfaults. If you're using RubyInline, place everything in the same inline block per class. Use private as a method afterward: class JACK::Client inline do |builder| builder.c <<-C /* define connect */ C end private :connect end There are several strategies to wrapping C libraries in a class so they are initialized properly. This uses ::allocate: http://github.com/drbrain/ffmpeg-rb/blob/master/lib/ffmpeg/fifo.rb This uses ::new: http://github.com/drbrain/ffmpeg-rb/blob/master/lib/ffmpeg/frame_buffer.rb This uses a custom method ::for_decoder: http://github.com/drbrain/ffmpeg-rb/blob/master/lib/ffmpeg/codec.rb Also, your extension doesn't make much use of RubyInline's helpfulness. RubyInline will automatically perform input and output casts for you. Connect should be a class method written like: builder.c_singleton <<-C static VALUE connect(char *name) { jack_client_t *client; client = jack_client_new(name); if (client == 0) rb_raise(rb_eRuntimeError, "cannot connect to JACK server"); /* guessing at free function */ return Data_Wrap_Struct(self, NULL, jack_client_close, client); } C With jack_get_sample_rate bound like: builder.c <<-C static jack_nframes_t sample_rate() { /* rubyish method name */ jack_client_t *client; Data_Get_Struct(self, jack_client_t, client); return jack_get_sample_rate(client); } C and a type converter: builder.alias_type_converter 'unsigned long', 'jack_nframes_t'