[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Sharing constants between C and Ruby code

Nathaniel Trellice

1/11/2007 12:02:00 PM

Hello,

I'm new to ruby, but fairly experienced in C. I am using Ruby on Rails
to chat to a postgres database. I have some C functions that I can run
in the database backend. I would like to use constants defined in C
header files, e.g "#define MY_CONSTANT 100" within ruby code. I know I
can similarly define a constant in ruby, i.e. "MY_CONSTANT=100", but
given that I have quite a few of these, and synchronising the two files
could become tricky, is there some (preferably simple) clever way/hack
that I can define constants in a single file and use them both in C and
in Ruby?

Thanks,
Nat

--
Posted via http://www.ruby-....

8 Answers

Simen

1/11/2007 12:08:00 PM

0

On 1/11/07, Nathaniel Trellice <naptrel@yahoo.co.uk> wrote:
> Hello,
>
> I'm new to ruby, but fairly experienced in C. I am using Ruby on Rails
> to chat to a postgres database. I have some C functions that I can run
> in the database backend. I would like to use constants defined in C
> header files, e.g "#define MY_CONSTANT 100" within ruby code. I know I
> can similarly define a constant in ruby, i.e. "MY_CONSTANT=100", but
> given that I have quite a few of these, and synchronising the two files
> could become tricky, is there some (preferably simple) clever way/hack
> that I can define constants in a single file and use them both in C and
> in Ruby?
>

I don't see how you'd share C preprocessor constants between Ruby and
C, since they're not available at runtime, unless you run the C
preprocessor on both Ruby and C files (oh, the horror).

> Thanks,
> Nat
>
> --
> Posted via http://www.ruby-....
>
>


--
- Simen

Jano Svitok

1/11/2007 1:15:00 PM

0

On 1/11/07, vincent.fourmond@9online.fr <vincent.fourmond@9online.fr> wrote:
> ----- Original Message -----
> From: Nathaniel Trellice
> Date: Thursday, January 11, 2007 1:02 pm
> Subject: Sharing constants between C and Ruby code
> To: ruby-talk@ruby-lang.org (ruby-talk ML)
>
> > Hello,
> >
> > I'm new to ruby, but fairly experienced in C. I am using Ruby on Rails
> > to chat to a postgres database. I have some C functions that I can run
> > in the database backend. I would like to use constants defined in C
> > header files, e.g "#define MY_CONSTANT 100" within ruby code. I
> > know I
> > can similarly define a constant in ruby, i.e. "MY_CONSTANT=100", but
> > given that I have quite a few of these, and synchronising the two
> > filescould become tricky, is there some (preferably simple) clever
> > way/hackthat I can define constants in a single file and use them
> > both in C and
> > in Ruby?
>
> I think the best way is the following: have all you C defines in a separate
> .h file (and only those). Write a small ruby script taking all the lines in
> your header through something like (untested):
>
> open(file) do |f|
> for line in f
> if line =~ /#define\s+(\w+)\s+(\S+)/
> puts "#{$1} = #[$2}"
> end
> end
> end
>
> Use this to create a .rb file, and have it regenerated through a Makefile.

This is seems to me as the best approach - you could create extension
that you'd require, and that would define those constants, but it will
be unnecessarily complicated.
Just write your header to be easily parsable and you're done.

Alexandru E. Ungur

1/11/2007 1:16:00 PM

0

>>> sender: "Nathaniel Trellice" date: "Thu, Jan 11, 2007 at 09:01:50PM +0900" <<<EOQ
> Hello,
>
> I'm new to ruby, but fairly experienced in C. I am using Ruby on Rails
> to chat to a postgres database. I have some C functions that I can run
> in the database backend. I would like to use constants defined in C
> header files, e.g "#define MY_CONSTANT 100" within ruby code. I know I
> can similarly define a constant in ruby, i.e. "MY_CONSTANT=100", but
> given that I have quite a few of these, and synchronising the two files
> could become tricky, is there some (preferably simple) clever way/hack
> that I can define constants in a single file and use them both in C and
> in Ruby?
Hello,

I've had a similar problem to solve when I had a mixed PHP/Ruby project.
I ended up using a separate file from both PHP and Ruby, like:

0 = some_constant
1 = some_other_constant
etc.

which was trivial to parse and turn into constants into either of them.
It actually made the project cleaner to have the constants defined like
that so I ended up putting all the constants there not just the common
ones between PHP and Ruby scripts.

Later, for parsing that same definitions file from C, I found a nice
library: http://sbooth.org/ccl/...


All the best,
Alex

Nathaniel Trellice

1/11/2007 1:23:00 PM

0

Thanks for the ideas.

What I was thinking of doing was writing a Ruby class (in C) which has
the constants as class constants. This way, compiling the class will
pull in the #defines from the C header file, and they'll be available
within Ruby from my class. But, being new to ruby, I was hoping to avoid
having to figure out how to write a Ruby class in C at this stage of my
ruby development!
Thanks again
Nat

--
Posted via http://www.ruby-....

Gary Wright

1/11/2007 2:03:00 PM

0


On Jan 11, 2007, at 8:23 AM, Nathaniel Trellice wrote:
> What I was thinking of doing was writing a Ruby class (in C) which has
> the constants as class constants. This way, compiling the class will
> pull in the #defines from the C header file, and they'll be available
> within Ruby from my class. But, being new to ruby, I was hoping to
> avoid
> having to figure out how to write a Ruby class in C at this stage
> of my
> ruby development!

I don't think that approach would buy you much. You would still have
to maintain (by hand) a C file that mapped the C constants (from the .h
file) into Ruby constants. I'm not a Ruby's internal programmer but
I imagine you would have to have something like:

rb_constant_set( klass, 'MY_CONSTANT', MY_CONSTANT)

for every single constant. Note: I made up the function name and API,
but
you would have to explicitly bind the string 'MY_CONSTANT' to the value
represented by the MY_CONSTANT macro via some sort of function call.

I can't imagine that maintaining that C file by hand is any easier than
the simple parsing suggestion that has already been described to
generate
a pure Ruby class. Alternatively, you could describe your constants
via something like YAML and write (in Ruby!) code to generate a C header
file for the constants and Ruby class for your use in the Ruby side
of things.

Even easier, something like:

class Constants
A = 100
B = 200
C = A + B

def self.to_h
constants.sort.inject("") { |t,c|
t << "#define #{c} #{const_get(c)}\n"
}
end
end

Now you can maintain this class directly and have it generate your
C .h file
via:

open("constants.h", "w") { |f|
f.write Constants.to_h
}

Anyway, I think there are lots of ways to handle your situation
without having
to dive into writing Ruby extensions and/or classes in C.



Gary Wright




Rob Biedenharn

1/11/2007 2:05:00 PM

0


On Jan 11, 2007, at 8:23 AM, Nathaniel Trellice wrote:

> Thanks for the ideas.
>
> What I was thinking of doing was writing a Ruby class (in C) which has
> the constants as class constants. This way, compiling the class will
> pull in the #defines from the C header file, and they'll be available
> within Ruby from my class. But, being new to ruby, I was hoping to
> avoid
> having to figure out how to write a Ruby class in C at this stage
> of my
> ruby development!
> Thanks again
> Nat
>
> --
> Posted via http://www.ruby-....
>

It's really not as hard as you think. In fact, I whipped this up in
15 minutes (and that's because I had to look up the functions!)

If the set of constants is fixed, you need only create the C file
once. If not, then a script to generate your version of
"rb_my_constants.c" with the right set of rb_define_const(...) lines
would be a slightly better way to go than having to parse and
generate the ruby module directly. (Note, module rather than class
since you didn't indicate there was any methods to share, but calling
a C function as a Ruby method is almost just as easy.)

-Rob

rab:c $ mkdir my_constants
rab:c $ cd my_constants/
rab:my_constants $ head -100 my_constants.h rb_my_constants.c extconf.rb
==> my_constants.h <==
#define MY_CONSTANT 100
#define YOUR_CONSTANT 102
#define HIS_CONSTANT 0xCAFE

==> rb_my_constants.c <==
#include "ruby.h"

#include "my_constants.h"

static int id_my_constants;

VALUE mMyConstants;

void Init_my_constants()
{
mMyConstants = rb_define_module("MyConstants");
rb_define_const(mMyConstants, "MY_CONSTANT", INT2NUM
(MY_CONSTANT));
rb_define_const(mMyConstants, "YOUR_CONSTANT", INT2NUM
(YOUR_CONSTANT));
rb_define_const(mMyConstants, "HIS_CONSTANT", INT2NUM
(HIS_CONSTANT));
}

==> extconf.rb <==
require 'mkmf'
create_makefile("my_constants")

rab:my_constants $ ruby extconf.rb
creating Makefile
rab:my_constants $ make
gcc -I. -I/opt/local/lib/ruby/1.8/i686-darwin8.8.1 -I/opt/local/lib/
ruby/1.8/i686-darwin8.8.1 -I. -O -pipe -I/opt/local/include -fno-
common -O -pipe -I/opt/local/include -fno-common -pipe -fno-common -
c rb_my_constants.c
cc -dynamic -bundle -undefined suppress -flat_namespace -L/opt/local/
lib -L"/opt/local/lib" -o my_constants.bundle rb_my_constants.o -
lruby -lpthread -ldl -lobjc
/usr/bin/ld: warning multiple definitions of symbol _setregid
/opt/local/lib/libruby.dylib(process.o) definition of _setregid
/usr/lib/gcc/i686-apple-darwin8/4.0.1/../../../libpthread.dylib
(setregid.So) definition of _setregid
/usr/bin/ld: warning multiple definitions of symbol _setreuid
/opt/local/lib/libruby.dylib(process.o) definition of _setreuid
/usr/lib/gcc/i686-apple-darwin8/4.0.1/../../../libpthread.dylib
(setreuid.So) definition of _setreuid

rab:my_constants $ ls -l
total 72
-rw-r--r-- 1 rab rab 3585 Jan 11 08:50 Makefile
-rw-r--r-- 1 rab rab 47 Jan 11 08:38 extconf.rb
-rwxr-xr-x 1 rab rab 13296 Jan 11 08:51 my_constants.bundle
-rw-r--r-- 1 rab rab 83 Jan 11 08:38 my_constants.h
-rw-r--r-- 1 rab rab 402 Jan 11 08:49 rb_my_constants.c
-rw-r--r-- 1 rab rab 1304 Jan 11 08:51 rb_my_constants.o

rab:my_constants $ irb -rmy_constants
>> MyConstants
=> MyConstants
>> MyConstants.constants
=> ["MY_CONSTANT", "HIS_CONSTANT", "YOUR_CONSTANT"]
>> MyConstants::MY_CONSTANT
=> 100
>> MyConstants::YOUR_CONSTANT
=> 102
>> MyConstants::HIS_CONSTANT
=> 51966
>> MyConstants::HIS_CONSTANT.to_s(16)
=> "cafe"
>> exit


Rob Biedenharn http://agileconsult...
Rob@AgileConsultingLLC.com



Gary Wright

1/11/2007 3:01:00 PM

0


On Jan 11, 2007, at 9:04 AM, Rob Biedenharn wrote:
> rb_define_const(mMyConstants, "MY_CONSTANT", INT2NUM
> (MY_CONSTANT));
> rb_define_const(mMyConstants, "YOUR_CONSTANT", INT2NUM
> (YOUR_CONSTANT));
> rb_define_const(mMyConstants, "HIS_CONSTANT", INT2NUM
> (HIS_CONSTANT));

Hah! I wasn't too far off with my guess of:
> rb_constant_set( klass, 'MY_CONSTANT', MY_CONSTANT)


Anyway, you are still stuck with having to keep the C .h file and the
Ruby
c extension in sync by hand. I'd pick any other scheme that allowed
you
to only worry about maintaining a single file with the constant
definitions.

Gary Wright




Rob Biedenharn

1/11/2007 3:41:00 PM

0


On Jan 11, 2007, at 10:01 AM, gwtmp01@mac.com wrote:

>
> On Jan 11, 2007, at 9:04 AM, Rob Biedenharn wrote:
>> rb_define_const(mMyConstants, "MY_CONSTANT", INT2NUM
>> (MY_CONSTANT));
>> rb_define_const(mMyConstants, "YOUR_CONSTANT", INT2NUM
>> (YOUR_CONSTANT));
>> rb_define_const(mMyConstants, "HIS_CONSTANT", INT2NUM
>> (HIS_CONSTANT));
>
> Hah! I wasn't too far off with my guess of:
>> rb_constant_set( klass, 'MY_CONSTANT', MY_CONSTANT)
>
>
> Anyway, you are still stuck with having to keep the C .h file and
> the Ruby
> .c extension in sync by hand. I'd pick any other scheme that
> allowed you
> to only worry about maintaining a single file with the constant
> definitions.
>
> Gary Wright

It depends on whether the OP is adding new constants to the file
(#define HER_CONSTANT 105) or just changing the values (#define
MY_CONSTANT 42).

You could always generate the .c file from the .h if that were a
problem -- and that's what others suggested doing from .h to .rb
directly. This solution however, lets the C preprocessor and/or
compiler do the dirty work of parsing the value of the #define. If
they are non-trivial, this might be a big win. If these constants
are always numbers, hand-coding the rb_my_constants.c file may be the
way to go (or you'd have to make parsing the .h file smarter (or give
it hints?)).

Besides, if new constants are added, you'd have to know they existed
to use them in the Ruby code anyway.

Perhaps Nathaniel can clear up the mystery for us by telling us what
assumptions *he* is making and what solutions will work better for
his situation.

-Rob

Rob Biedenharn http://agileconsult...
Rob@AgileConsultingLLC.com