On Nov 20, 2009, at 06:26, Marcin L. wrote:
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 :
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’