Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

RubyInline - passing pointer from one function to another

5 views
Skip to first unread message

Marcin Lewandowski

unread,
Nov 20, 2009, 9:15:18 AM11/20/09
to
Hi,

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?

Thanks in advance,

m.

Brian Candler

unread,
Nov 20, 2009, 12:15:51 PM11/20/09
to
Marcin Lewandowski wrote:
> I'm trying to write ruby interface to JACK audio library. I've chosen
> RubyInline due it's simplicity.

I'm afraid I'm not answering your question, but have you looked at FFI?
This is designed to do exactly what you want, namely, calling an
existing C library from Ruby.

--
Posted via http://www.ruby-forum.com/.

Marcin Lewandowski

unread,
Nov 20, 2009, 1:14:09 PM11/20/09
to
Hi,

seems that could be helpful. I'll check FFI.

m.

Eric Hodel

unread,
Nov 23, 2009, 6:18:04 PM11/23/09
to

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'

0 new messages