From: Charles Mills Date: 2004-11-20T05:12:15+09:00 Subject: Re: [ARTICLE] Extending Ruby with C On Nov 19, 2004, at 11:58 AM, Daniel Berger wrote: > gabriele renzi wrote in message > news:... >> An article from Garrett Rooney just appeared at OnLamp.com >> you can read it at >> http://www.onlamp.com/pub/a/onlamp/2004/11/18/extending_ruby.html >> (....) > > One thing I wish C extension authors would stop doing is manually > counting variable length argument lists. From the article: > > static VALUE > writer_begin_element (int argc, VALUE *argv, VALUE self) > { > genxWriter w; > VALUE xmlns, name; > > switch (argc): > > .... > > If I'm not mistaken, this style of argument checking has already led > to more than one bug in the Ruby source code itself. Knock it off and > use rb_scan_args(). Also, I find that starting all VALUE variables > with 'rb' leads to clearer code, since it makes it immediately obvious > which values are Ruby VALUE's versus C variables. Sounds like a good practice. > static VALUE > writer_begin_element (int argc, VALUE *argv, VALUE self) > { > genxWriter w; > VALUE rbName, rbXmlns; > > /* One mandatory argument, one optional argument */ > rb_scan_args(argc,argv,"11",&rbName,&rbXmlns); > > Check_Type(rbName,T_STRING); > Check_Type(rbXmlns,T_STRING); > > .... If you use camel case for your variable names this seems OK, but I would worry about creating conflicts with existing Ruby method names and global variables - since they all start with 'rb'. > > This is both shorter, more concise and easier to read all in one shot. > It's also a smarter API, since in both cases the name is mandatory, > while the namespace is optional, afaict. So, now the front end looks > like this: > > Genx::Writer#begin_element(name,namespace=nil) > > Other than a minor modification in GENX4R_ERR, checking against Qnil > vs 0, this code is identical. No big, ugly switch. No need to > manually raise an ArgumentError if the arg count is wrong. Nice and > tidy. > I have found that making judicious use of StingValue(), NUM2LONG(), rb_Array(), and friends has advantages over using Check_Type() - you get better error messages and you add compatibility with other extensions/classes that make use "to_str", "to_int", "to_a", ... the later being a big plus. -Charlie