I’m writing a Ruby extension in C to utilize a library (tsk3, aka. The
Sleuth Kit) for opening disk images, and I found I couldn’t get
Data_Get_Struct to return the Struct built during initialization.
This seemed odd as I built my class “by the book”, and could get data
from inside the Struct during initialization.
The only workaround I found was referring to DATA_PTR directly (see code
below), which is odd because I found few examples of this in the
community. I thought the whole point of Data_Get_Struct(self, C TYPE,
ptr) was to fetch the Struct wrapped by ‘self’ and return a reference
(ptr) to it. I’m developing on 1.8.7, but will be moving on to 1.9
soon, and would like to know if I’m about to make a major mistake by
using what looks like an old workaround. Why would VALUE self not be
sufficient for Ruby to fetch the Struct using the Data_Get_Struct macro?
Is assigning DATA_PTR(self) to the C pointer going to wreck the ruby
Object being created?
#include <stdio.h>
#include <tsk3/libtsk.h>
#include <ruby.h>
// prototypes
static VALUE rb_mtsk4r;
static VALUE rb_cClass1;
static VALUE initialize(VALUE self);
static VALUE sector_size(VALUE self);
VALUE klass;
// alloc & dealloc
static void deallocate(void * image){
xfree((TSK_IMG_INFO *)image);
}
static VALUE allocate(VALUE klass){
TSK_IMG_INFO *ptr;
return Data_Make_Struct(klass, TSK_IMG_INFO, 0, xfree, ptr);
}
// init a FirstClass (Image) object
VALUE initialize(VALUE self){
char * filename;
filename = “/tmp/test.image”;
TSK_IMG_INFO *image; // declare inner struct
Data_Get_Struct(self, TSK_IMG_INFO, image); // fetch inner struct from
self
// use function from libtsk3 to open disk image
image = tsk_img_open_sing(filename, TSK_IMG_TYPE_DETECT, 0);
fprintf(stdout, “image size: %d\tsector size:%d\n”, (int)image->size,
(int)image->sector_size);
Check_Type(self, T_DATA);
// done
fprintf(stdout, “DATA_PTR(self): %lu\n”, (long)DATA_PTR(self));
DATA_PTR(self) = image; // Not sure I should be doing this…
fprintf(stdout, “DATA_PTR(self): %lu\n”, (long)DATA_PTR(self));
return self;
}
static VALUE sector_size(VALUE self){
TSK_IMG_INFO * image;
Data_Get_Struct(self, TSK_IMG_INFO, image);
return INT2NUM(image->sector_size);
}
void Init_tsk4r() {
rb_mtsk4r = rb_define_module(“TSK”);
// class definition
rb_cClass1 = rb_define_class_under(rb_mtsk4r, “Image”, rb_cObject);
// allocation function
rb_define_alloc_func(rb_cClass1, allocate);
// object methods
rb_define_method(rb_cClass1, “initialize”, initialize, 0);
rb_define_method(rb_cClass1, “sector_size”, sector_size, 0);
}