Tenderlove Making

Writing Ruby C Extensions: Part 2

LIBDIR      = Config::CONFIG['libdir']
INCLUDEDIR  = Config::CONFIG['includedir']

HEADER_DIRS = [
  # First search /opt/local for macports
  '/opt/local/include',

  # Then search /usr/local for people that installed from source
  '/usr/local/include',

  # Check the ruby install locations
  INCLUDEDIR,

  # Finally fall back to /usr
  '/usr/include',
]

LIB_DIRS = [
  # First search /opt/local for macports
  '/opt/local/lib',

  # Then search /usr/local for people that installed from source
  '/usr/local/lib',

  # Check the ruby install locations
  LIBDIR,

  # Finally fall back to /usr
  '/usr/lib',
]

dir_config('stree', HEADER_DIRS, LIB_DIRS)
unless find_header('stree/lst_string.h')
  abort "libstree is missing.  please install libstree"
end
unless find_library('stree', 'lst_stree_free')
  abort "libstree is missing.  please install libstree"
end
create_makefile('stree/stree')
string = STree::String.new 'foo'
assert_equal 3, string.length
require 'stree'
require 'test/unit'

module STree
  class TestString < Test::Unit::TestCase
    def test_length
      string = STree::String.new 'foo'
      assert_equal 3, string.length
    end

    def test_type_error
      assert_raises(TypeError) do
        STree::String.new Object.new
      end
    end
  end
end
#ifndef RUBY_STREE
#define RUBY_STREE

#include <ruby.h>;
#include <stree/lst_string.h>;

#include <stree_string.h>;

extern VALUE mSTree;

#endif
#include <stree.h>

VALUE mSTree;

void Init_stree()
{
  mSTree = rb_define_module("STree");

  Init_stree_string();
}
#ifndef RUBY_STREE_STRING
#define RUBY_STREE_STRING

#include <stree.h>

void Init_stree_string();

#endif
#include <stree_string.h>

void Init_stree_string()
{
  VALUE cSTreeString = rb_define_class_under(mSTree, "String", rb_cObject);
}
module STree
  class String
  end
end
  1) Error:
test_length(STree::TestString):
ArgumentError: wrong number of arguments (1 for 0)
    ./test/test_stree_string.rb:7:in `initialize'
    ./test/test_stree_string.rb:7:in `new'
    ./test/test_stree_string.rb:7:in `test_length'
void Init_stree_string()
{
  VALUE cSTreeString = rb_define_class_under(mSTree, "String", rb_cObject);

  rb_define_alloc_func(cSTreeString, allocate);
}
static VALUE allocate(VALUE klass)
{
  LST_String * string = malloc(sizeof(LST_String));

  return Data_Wrap_Struct(klass, NULL, deallocate, string);
}
static void deallocate(void * string)
{
  lst_string_free((LST_String *)string);
}
void Init_stree_string()
{
  VALUE cSTreeString = rb_define_class_under(mSTree, "String", rb_cObject);

  rb_define_alloc_func(cSTreeString, allocate);
  rb_define_method(cSTreeString, "initialize", initialize, 1);
}
static VALUE initialize(VALUE self, VALUE rb_string)
{
  LST_String * string;
  void * data;

  Check_Type(rb_string, T_STRING);

  Data_Get_Struct(self, LST_String, string);

  data = calloc(RSTRING_LEN(rb_string), sizeof(char));
  memcpy(data, StringValuePtr(rb_string), RSTRING_LEN(rb_string));

  lst_string_init(
      string,
      data,
      sizeof(char),
      RSTRING_LEN(rb_string));

  return self;
}
  1) Error:
test_length(STree::TestString):
NoMethodError: undefined method `length' for #<STree::String:0x101f0e6f8>
    ./test/test_stree_string.rb:8:in `test_length'
void Init_stree_string()
{
  VALUE cSTreeString = rb_define_class_under(mSTree, "String", rb_cObject);

  rb_define_alloc_func(cSTreeString, allocate);
  rb_define_method(cSTreeString, "initialize", initialize, 1);
  rb_define_method(cSTreeString, "length", length, 0);
}
static VALUE length(VALUE self)
{
  LST_String * string;

  Data_Get_Struct(self, LST_String, string);

  return INT2NUM(lst_string_get_length(string));
}
Loaded suite -e
Started
..
Finished in 0.000873 seconds.

2 tests, 2 assertions, 0 failures, 0 errors

<3<3<3<3<3<3<3<3 –tenderlove

« go back