Writing Ruby C Extensions: Part 2
Dec 11, 2010 @ 4:25 pmLIBDIR = 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