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);

}

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