Forum: Ruby How to do conditional compile for Ruby 1.9 in a C extension?

A50dcaaf8e545e6cc1fb4e32919be6ad?d=identicon&s=25 Jason Garber (jgarber)
on 2009-02-19 18:21
I'm working on updating RedCloth for Ruby 1.9.  Since the output of
#singleton_methods changed from strings to symbols, I think I need a
conditional compile.  Here's what I tried:

#if RUBY_VERSION < 0x10900
  if (rb_ary_includes(rb_funcall(self, rb_intern("singleton_methods"),
0), btype)) {
#else
  if (rb_ary_includes(rb_funcall(self, rb_intern("singleton_methods"),
0), rb_str_intern(btype))) {
#endif
A50dcaaf8e545e6cc1fb4e32919be6ad?d=identicon&s=25 Jason Garber (jgarber)
on 2009-02-19 18:24
Sorry, ruby-forum cut off the rest of what I wrote.  The above code
example is doing the first way for both 1.8 and 1.9.  What's the proper
way to detect the ruby version or the feature?

Thanks!
Jason Garber
8f6f95c4bd64d5f10dfddfdcd03c19d6?d=identicon&s=25 Rick Denatale (rdenatale)
on 2009-02-19 18:53
(Received via mailing list)
On Thu, Feb 19, 2009 at 12:21 PM, Jason Garber <jg@jasongarber.com>
wrote:

> #endif
>

from version.h in Ruby 1.9
define RUBY_VERSION "1.9.2"
#define RUBY_RELEASE_DATE "2009-02-16"
#define RUBY_PATCHLEVEL -1
#define RUBY_BRANCH_NAME "trunk"

#define RUBY_VERSION_MAJOR 1
#define RUBY_VERSION_MINOR 9
#define RUBY_VERSION_TEENY 1
#define RUBY_RELEASE_YEAR 2009
#define RUBY_RELEASE_MONTH 2
#define RUBY_RELEASE_DAY 16

and for Ruby 1.8.6
#define RUBY_VERSION "1.8.6"
#define RUBY_RELEASE_DATE "2007-11-12"
#define RUBY_VERSION_CODE 186
#define RUBY_RELEASE_CODE 20071112
#define RUBY_PATCHLEVEL 5000

#define RUBY_VERSION_MAJOR 1
#define RUBY_VERSION_MINOR 8
#define RUBY_VERSION_TEENY 6
#define RUBY_RELEASE_YEAR 2007
#define RUBY_RELEASE_MONTH 11
#define RUBY_RELEASE_DAY 12


so I think that you want something like

#if RUBY_VERSION < '1.9.0'
   do pre 1.9 stuff
#else
   do 1.9 stuff
#end

Matz is careful to use Ruby version numbers which can be compared using
string comparison.

or

#if RUBY_VERSION_MAJOR = 1 && RUBY_VERSION_MINOR == 9
  do 1.9 stuff
#else
  do 1.8 stuff
#end

or some variant on those.

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
A50dcaaf8e545e6cc1fb4e32919be6ad?d=identicon&s=25 Jason Garber (jgarber)
on 2009-02-19 19:21
> Matz is careful to use Ruby version numbers which can be compared using
> string comparison.

Nice!  I didn't know that, so where I'd seen string comparisons on the
version number before, I just thought it was foolhardy.

Thanks for the help.

Jason
A50dcaaf8e545e6cc1fb4e32919be6ad?d=identicon&s=25 Jason Garber (jgarber)
on 2009-02-19 21:59
It's not working for me.  In my C file I tested the presence of those
variables like so:

#ifdef RUBY_VERSION_MAJOR
    printf("RUBY_VERSION_MAJOR defined\n");
#endif
#ifndef RUBY_VERSION_MAJOR
    printf("RUBY_VERSION_MAJOR NOT defined ******\n");
#endif

and it outputs RUBY_VERSION_MAJOR NOT defined ******

Why aren't the RUBY_VERSION constants defined?
8f6f95c4bd64d5f10dfddfdcd03c19d6?d=identicon&s=25 Rick Denatale (rdenatale)
on 2009-02-19 22:32
(Received via mailing list)
did you include version.h?

On Thu, Feb 19, 2009 at 3:59 PM, Jason Garber <jg@jasongarber.com>
wrote:

> and it outputs RUBY_VERSION_MAJOR NOT defined ******
>
> Why aren't the RUBY_VERSION constants defined?
> --
> Posted via http://www.ruby-forum.com/.
>
>


--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
A50dcaaf8e545e6cc1fb4e32919be6ad?d=identicon&s=25 Jason Garber (jgarber)
on 2009-02-20 02:45
version.h couldn't be found.  I've read that version.h is deprecated in
Ruby 1.9.  There's either got to be another way to detect the change or
a way to work around it.  I'd just use map! to convert the strings to
symbols if I knew how to do it in C.
3afd3e5e05dc9310c89aa5762cc8dd1d?d=identicon&s=25 Tim Hunter (Guest)
on 2009-02-20 03:43
(Received via mailing list)
Jason Garber wrote:
> version.h couldn't be found.  I've read that version.h is deprecated in
> Ruby 1.9.  There's either got to be another way to detect the change or
> a way to work around it.  I'd just use map! to convert the strings to
> symbols if I knew how to do it in C.

I'm not saying this is the best way (maybe Nobu can provide a better
answer), but if you can be sure that mkmf.rb is being executed by the
same version of Ruby, then you could cook up a feature test in your
extconf.rb that would create a preprocessor symbol to test. Determine
what singleton_methods is doing, then call $defs.push to set a symbol:

     $defs.push("-DNEW_SINGLETON_METHODS")
F1d6cc2b735bfd82c8773172da2aeab9?d=identicon&s=25 Nobuyoshi Nakada (nobu)
on 2009-02-20 05:08
(Received via mailing list)
Hi,

At Fri, 20 Feb 2009 02:21:24 +0900,
Jason Garber wrote in [ruby-talk:328775]:
> I'm working on updating RedCloth for Ruby 1.9.  Since the output of
> #singleton_methods changed from strings to symbols, I think I need a
> conditional compile.  Here's what I tried:

The output?  You convert the argument.

> #if RUBY_VERSION < 0x10900
>   if (rb_ary_includes(rb_funcall(self, rb_intern("singleton_methods"),
> 0), btype)) {
> #else
>   if (rb_ary_includes(rb_funcall(self, rb_intern("singleton_methods"),
> 0), rb_str_intern(btype))) {
> #endif

And #singleton_methods takes a flag, anything not only string
and symbol can be true.
A50dcaaf8e545e6cc1fb4e32919be6ad?d=identicon&s=25 Jason Garber (jgarber)
on 2009-02-20 10:59
Sorry, nobu, I didn't follow you.  Try again?
F1d6cc2b735bfd82c8773172da2aeab9?d=identicon&s=25 Nobuyoshi Nakada (nobu)
on 2009-02-20 20:11
(Received via mailing list)
Hi,

At Fri, 20 Feb 2009 18:58:55 +0900,
Jason Garber wrote in [ruby-talk:328856]:
> Sorry, nobu, I didn't follow you.  Try again?

Sorry, I misread the parentheses.

> I'm working on updating RedCloth for Ruby 1.9.  Since the output of
> #singleton_methods changed from strings to symbols, I think I need a
> conditional compile.  Here's what I tried:

It's a problem indeed.

> #if RUBY_VERSION < 0x10900
>   if (rb_ary_includes(rb_funcall(self, rb_intern("singleton_methods"),
> 0), btype)) {
> #else
>   if (rb_ary_includes(rb_funcall(self, rb_intern("singleton_methods"),
> 0), rb_str_intern(btype))) {
> #endif

Do you really need to know only if singleton method is defined,
not just self responds to it?

We may have to add a new macro in ruby.h.
A50dcaaf8e545e6cc1fb4e32919be6ad?d=identicon&s=25 Jason Garber (jgarber)
on 2009-02-20 20:49
I ended up sidestepping the whole issue completely and writing a new
accessor, #formatter_methods, that just returned singleton_methods.map!
{|method| method.to_sym }.  The reasons for needing #singleton_methods
and not #respond_to? or #method_defined? are hard to explain, but you
can probably understand it fairly quickly by looking at the source:
http://github.com/jgarber/redcloth/commit/c941af12...

A macro would've been nice, but it worked out okay for me anyway.
Thanks for your help!

Jason
F1d6cc2b735bfd82c8773172da2aeab9?d=identicon&s=25 Nobuyoshi Nakada (nobu)
on 2009-02-22 11:37
(Received via mailing list)
Hi,

At Sat, 21 Feb 2009 04:48:49 +0900,
Jason Garber wrote in [ruby-talk:328928]:
> A macro would've been nice, but it worked out okay for me anyway.

Do you have any suggestion for the name?  My candidate is
USE_SYMBOL_AS_METHOD_NAME.
A50dcaaf8e545e6cc1fb4e32919be6ad?d=identicon&s=25 Jason Garber (jgarber)
on 2009-02-22 23:10
Nobuyoshi Nakada wrote:
> Hi,
>
>
> Do you have any suggestion for the name?  My candidate is
> USE_SYMBOL_AS_METHOD_NAME.

Sounds great to me!  Thanks!
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.