Friday, July 18, 2008

Ruby 1.9 C API - Object Instances


To Create a new instance of an object with class Class we will do this:

VALUE obj;

obj = rb_obj_alloc(Class); // Allocate space and create new instance
rb_obj_call_init(obj, 0, 0); // We call the initialize method for the object

Remember rb_obj_alloc() does not initialize the object and will seg fault if you use any custom data types in the object.

The 2nd and 3rd parameters of rb_obj_call_init() are the argument count (argc) and the constructor parameters array ( VALUE* ).

Friday, July 11, 2008

Ruby C API - Classes I


To create a class:


VALUE rb_define_class("name", parent_class);
VALUE rb_define_class_under(module_or_class, "name", parent_class);


To create a method:

rb_define_method(class, "name", c_function, argc)

argc is the number of arguments of the function, not including the first parameter of the c_function which would be the instance variable. Default Parameters can be implemented by setting this number to negative. (-1 would mean variable number of parameters, -2 would create an array to store the arguments)

"name" is the name of the method in ruby, for setter methods you would add the = to the name just like in ruby ( ie "name=" ). The same with operator for the [] operator you will use the string "[]" or "[]=".

The format of a ruby function accepting a variable number of arguments (argc = -1) would be like this:


VALUE function( int argc, VALUE* args, VALUE instance );


argc is the number of arguments passed.
args is an array containing the arguments.
instance is the instance of the object.

The format for a ruby function accepting an array of arguments (argc = -2) :


VALUE function( VALUE instance, VALUE array_of_arguments);


To access instance variables you will use this two methods:


rb_iv_get(instance, "variable");
rb_iv_set(instance, "variable", new_value);


stay tuned for part II.

Thursday, July 10, 2008

Firefox Download Antivirus??


I recently noticed that firefox stopped responding for a couple of seconds every time i downloaded a file. The cause was the new virus scan feature. To disable this ( I tried Tools/Options but couln't find anything ) go to about:config and search for browser.download.manager.scanWhenDone then set it to false.

Sunday, July 6, 2008

Ruby 1.9 C API - Exceptions I


rb_raise(exception_object, string_message);
rb_raise will try to call exception_object.new and display string-message as the exception error message.

Some of the built-in exceptions that can be raised are:
rb_eArgError
rb_eEOFError
rb_eException
rb_eFatal
rb_eFloatDomainError
rb_eIndexError
rb_eInterrupt
rb_eIOError
rb_eKeyError
rb_eLoadError
rb_eLocalJumpError
rb_eNameError
rb_eNoMemError
rb_eNoMethodError
rb_eNotImpError
rb_eRangeError
rb_eRegexpError
rb_eRuntimeError
rb_eScriptError
rb_eSecurityError
rb_eSignal
rb_eStandardError
rb_eStopIteration
rb_eSyntaxError
rb_eSysStackError
rb_eSystemCallError
rb_eSystemExit
rb_eThreadError
rb_eTypeError
rb_eZeroDivError

Saturday, July 5, 2008

Listing RSS items with PHP in 3 lines



$rss = simplexml_load_file("rss feed url");
foreach ($rss->channel->item as $k)
echo $k->title . "\n";

In 4 lines with HTML formatting!!

$rss = simplexml_load_file("blog rss url!");
foreach ($rss->channel->item as $k)
$rss_list .= "<li>" . $k->title . "</li>\n";

$index_rss = "<ul>$rss_list</ul>";

Ruby 1.9 C API - Accepting Blocks


Executing the Block
rb_yield(Qnil);
Replace Qnil with the parameters you wish to pass to the block. The Result of the block is returned.
rb_block_given_p();
This function will tell you if a block was passed. Blocks are not counted as parameters so if your function only accepts a block then you need to specify 0 as the number of parameters.

Friday, July 4, 2008

Ruby 1.9 C API !! - Internal Structures


To access the internal structure of any Ruby object, 'ruby.h' defines the following macros:
#define RBASIC(obj) (R_CAST(RBasic)(obj))
#define ROBJECT(obj) (R_CAST(RObject)(obj))
#define RCLASS(obj) (R_CAST(RClass)(obj))
#define RMODULE(obj) RCLASS(obj)
#define RFLOAT(obj) (R_CAST(RFloat)(obj))
#define RSTRING(obj) (R_CAST(RString)(obj))
#define RREGEXP(obj) (R_CAST(RRegexp)(obj))
#define RARRAY(obj) (R_CAST(RArray)(obj))
#define RHASH(obj) (R_CAST(RHash)(obj))
#define RDATA(obj) (R_CAST(RData)(obj))
#define RSTRUCT(obj) (R_CAST(RStruct)(obj))
#define RBIGNUM(obj) (R_CAST(RBignum)(obj))
#define RFILE(obj) (R_CAST(RFile)(obj))
#define RRATIONAL(obj) (R_CAST(RRational)(obj))
#define RCOMPLEX(obj) (R_CAST(RComplex)(obj))


The most important are:
struct RFloat {
struct RBasic basic;
double float_value;
};

struct RBignum {
struct RBasic basic;
union {
struct {
long len;
BDIGIT *digits;
} heap;
BDIGIT ary[RBIGNUM_EMBED_LEN_MAX];
} as;
};

struct RBasic basic;
union {
struct {
long len;
char *ptr;
union {
long capa;
VALUE shared;
} aux;
} heap;
char ary[RSTRING_EMBED_LEN_MAX];
} as;

To Access the value of a float number you will call:

RFLOAT(ruby_value)->double_value;


Fixnum's (Integers) are stored differently:

10 in Ruby => (10 >> 1) in C
10 in C => (10 << 1 | 1) in Ruby
-10 in Ruby => (10 >> 1) in C
-10 in C => (10 >> 1 | 1) in Ruby (0xffffffed)

Bignums are usually 8 bytes (long long).