[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

[ANN] CplusRuby - Gluing C and Ruby

Michael Neumann

9/21/2007 7:01:00 PM

18 Answers

Daniel Berger

9/21/2007 9:54:00 PM

0



On Sep 21, 1:01 pm, Michael Neumann <mneum...@ntecs.de> wrote:
> Hi all,
>
> I am proud to announce my latest project called CplusRuby.
> Below I pasted it's README for further explanation.
> Alternatively read the following blog article:
>
> http://www.ntecs.de/blog/articles/2007/09/21/cplusruby-gluing-...

<snip>

First patch!

C:\Documents and Settings\djberge\My Documents\My Downloads\Ruby>diff -
u cplusruby.orig cplusruby.rb
--- cplusruby.orig Fri Sep 21 15:50:38 2007
+++ cplusruby.rb Fri Sep 21 15:49:04 2007
@@ -11,6 +11,10 @@
#
# Implements a simple ordered Hash
#
+require 'rbconfig'
+require 'win32/process' if RUBY_PLATFORM.match('mswin')
+include Config
+
class OHash < Hash
def []=(k, v)
@order ||= []
@@ -146,20 +150,28 @@
dir = File.dirname(file)
mod, ext = base.split(".")

+ make = RUBY_PLATFORM.match('mswin') ? 'nmake' : 'make'
+
File.open(file, 'w+') {|f| f << self.generate_code(mod) }
Dir.chdir(dir) do
- system("make clean")
+ system("#{make} clean")
+
pid = fork do
require 'mkmf'
$CFLAGS = cflags
$LIBS << (" " + libs)
create_makefile(mod)
- exec "make"
+ exec "#{make}"
end
_, status = Process.waitpid2(pid)
- raise if status.exitstatus != 0
+
+ if RUBY_PLATFORM.match('mswin')
+ raise if status != 0
+ else
+ raise if status.exitstatus != 0
+ end
end
- require "#{dir}/#{mod}.so"
+ require "#{dir}/#{mod}." + CONFIG['DLEXT']
end

def self.generate_code_for_class

Mostly fixes MS Windows issues, but the DLEXT bit also fixes platforms
that don't generate .so files (OS X, HP-UX).

Regards,

Dan


Konrad Meyer

9/21/2007 10:04:00 PM

0

Quoth Daniel Berger:
>
> On Sep 21, 1:01 pm, Michael Neumann <mneum...@ntecs.de> wrote:
> > Hi all,
> >
> > I am proud to announce my latest project called CplusRuby.
> > Below I pasted it's README for further explanation.
> > Alternatively read the following blog article:
> >
> > http://www.ntecs.de/blog/articles/2007/09/21/cplusruby-gluing-...
>
> <snip>
>
> First patch!
>
> C:\Documents and Settings\djberge\My Documents\My Downloads\Ruby>diff -
> u cplusruby.orig cplusruby.rb
> --- cplusruby.orig Fri Sep 21 15:50:38 2007
> +++ cplusruby.rb Fri Sep 21 15:49:04 2007
> @@ -11,6 +11,10 @@
> #
> # Implements a simple ordered Hash
> #
> +require 'rbconfig'
> +require 'win32/process' if RUBY_PLATFORM.match('mswin')
> +include Config
> +
> class OHash < Hash
> def []=(k, v)
> @order ||= []
> @@ -146,20 +150,28 @@
> dir = File.dirname(file)
> mod, ext = base.split(".")
>
> + make = RUBY_PLATFORM.match('mswin') ? 'nmake' : 'make'
> +
> File.open(file, 'w+') {|f| f << self.generate_code(mod) }
> Dir.chdir(dir) do
> - system("make clean")
> + system("#{make} clean")
> +
> pid = fork do
> require 'mkmf'
> $CFLAGS = cflags
> $LIBS << (" " + libs)
> create_makefile(mod)
> - exec "make"
> + exec "#{make}"
> end
> _, status = Process.waitpid2(pid)
> - raise if status.exitstatus != 0
> +
> + if RUBY_PLATFORM.match('mswin')
> + raise if status != 0
> + else
> + raise if status.exitstatus != 0
> + end
> end
> - require "#{dir}/#{mod}.so"
> + require "#{dir}/#{mod}." + CONFIG['DLEXT']
> end
>
> def self.generate_code_for_class
>
> Mostly fixes MS Windows issues, but the DLEXT bit also fixes platforms
> that don't generate .so files (OS X, HP-UX).
>
> Regards,
>
> Dan

Does the C->ruby mapping map between char * and Strings?

Thanks,
--
Konrad Meyer <konrad@tylerc.org> http://konrad.sobertil...

Konrad Meyer

9/21/2007 11:43:00 PM

0

Quoth Konrad Meyer:
> Quoth Daniel Berger:
> >
> > On Sep 21, 1:01 pm, Michael Neumann <mneum...@ntecs.de> wrote:
> > > Hi all,
> > >
> > > I am proud to announce my latest project called CplusRuby.
> > > Below I pasted it's README for further explanation.
> > > Alternatively read the following blog article:
> > >
> > > http://www.ntecs.de/blog/articles/2007/09/21/cplusruby-gluing-...
> >
> > <snip>
> >
> > First patch!
> >
> > C:\Documents and Settings\djberge\My Documents\My Downloads\Ruby>diff -
> > u cplusruby.orig cplusruby.rb
> > --- cplusruby.orig Fri Sep 21 15:50:38 2007
> > +++ cplusruby.rb Fri Sep 21 15:49:04 2007
> > @@ -11,6 +11,10 @@
> > #
> > # Implements a simple ordered Hash
> > #
> > +require 'rbconfig'
> > +require 'win32/process' if RUBY_PLATFORM.match('mswin')
> > +include Config
> > +
> > class OHash < Hash
> > def []=(k, v)
> > @order ||= []
> > @@ -146,20 +150,28 @@
> > dir = File.dirname(file)
> > mod, ext = base.split(".")
> >
> > + make = RUBY_PLATFORM.match('mswin') ? 'nmake' : 'make'
> > +
> > File.open(file, 'w+') {|f| f << self.generate_code(mod) }
> > Dir.chdir(dir) do
> > - system("make clean")
> > + system("#{make} clean")
> > +
> > pid = fork do
> > require 'mkmf'
> > $CFLAGS = cflags
> > $LIBS << (" " + libs)
> > create_makefile(mod)
> > - exec "make"
> > + exec "#{make}"
> > end
> > _, status = Process.waitpid2(pid)
> > - raise if status.exitstatus != 0
> > +
> > + if RUBY_PLATFORM.match('mswin')
> > + raise if status != 0
> > + else
> > + raise if status.exitstatus != 0
> > + end
> > end
> > - require "#{dir}/#{mod}.so"
> > + require "#{dir}/#{mod}." + CONFIG['DLEXT']
> > end
> >
> > def self.generate_code_for_class
> >
> > Mostly fixes MS Windows issues, but the DLEXT bit also fixes platforms
> > that don't generate .so files (OS X, HP-UX).
> >
> > Regards,
> >
> > Dan
>
> Does the C->ruby mapping map between char * and Strings?
>
> Thanks,
> --
> Konrad Meyer <konrad@tylerc.org> http://konrad.sobertil...

Okay, so I have added the following to DEFAULT_OPTIONS:

:int => {
:default => '0',
:ctype => 'int %s',
:ruby2c => '(int)NUM2INT(%s)',
:c2ruby => 'INT2NUM(%s)'},

:char_p => {
:default => '""',
:ctype => 'char *%s',
:ruby2c => 'StringValuePtr(%s)',
:c2ruby => 'rb_str_new2(%s)'}

My code is like this:

#---------------------start

require 'cplusruby'

class BankAccount < CplusRuby
property :balance, :int
property :name, :char_p

method_c :withdraw, %{int dollars}, %{
if (dollars <= selfc->balance){
selfc->balance -= dollars;
return true;
}
}

def initialize
end
end

CplusRuby.evaluate("foo.c", "-Os", "")

n = BankAccount.new
puts n.balance
puts n.name

#---------------------end

When I run it with ruby I get a whole bunch of errors stemming from
the fact that it generates C code that uses a type called
"BankAccount" without defining it anywhere (struct BankAccount is
defined though).

Ideas, suggestions, questions?

Thanks,
--
Konrad Meyer <konrad@tylerc.org> http://konrad.sobertil...

Konrad Meyer

9/22/2007 12:34:00 AM

0

Quoth Konrad Meyer:
> Quoth Daniel Berger:
> >
> > On Sep 21, 1:01 pm, Michael Neumann <mneum...@ntecs.de> wrote:
> > > Hi all,
> > >
> > > I am proud to announce my latest project called CplusRuby.
> > > Below I pasted it's README for further explanation.
> > > Alternatively read the following blog article:
> > >
> > > http://www.ntecs.de/blog/articles/2007/09/21/cplusruby-gluing-...
> >
> > <snip>
> >
> > First patch!
> >
> > C:\Documents and Settings\djberge\My Documents\My Downloads\Ruby>diff -
> > u cplusruby.orig cplusruby.rb
> > --- cplusruby.orig Fri Sep 21 15:50:38 2007
> > +++ cplusruby.rb Fri Sep 21 15:49:04 2007
> > @@ -11,6 +11,10 @@
> > #
> > # Implements a simple ordered Hash
> > #
> > +require 'rbconfig'
> > +require 'win32/process' if RUBY_PLATFORM.match('mswin')
> > +include Config
> > +
> > class OHash < Hash
> > def []=(k, v)
> > @order ||= []
> > @@ -146,20 +150,28 @@
> > dir = File.dirname(file)
> > mod, ext = base.split(".")
> >
> > + make = RUBY_PLATFORM.match('mswin') ? 'nmake' : 'make'
> > +
> > File.open(file, 'w+') {|f| f << self.generate_code(mod) }
> > Dir.chdir(dir) do
> > - system("make clean")
> > + system("#{make} clean")
> > +
> > pid = fork do
> > require 'mkmf'
> > $CFLAGS = cflags
> > $LIBS << (" " + libs)
> > create_makefile(mod)
> > - exec "make"
> > + exec "#{make}"
> > end
> > _, status = Process.waitpid2(pid)
> > - raise if status.exitstatus != 0
> > +
> > + if RUBY_PLATFORM.match('mswin')
> > + raise if status != 0
> > + else
> > + raise if status.exitstatus != 0
> > + end
> > end
> > - require "#{dir}/#{mod}.so"
> > + require "#{dir}/#{mod}." + CONFIG['DLEXT']
> > end
> >
> > def self.generate_code_for_class
> >
> > Mostly fixes MS Windows issues, but the DLEXT bit also fixes platforms
> > that don't generate .so files (OS X, HP-UX).
> >
> > Regards,
> >
> > Dan
>
> Does the C->ruby mapping map between char * and Strings?
>
> Thanks,
> --
> Konrad Meyer <konrad@tylerc.org> http://konrad.sobertil...

Also, is there a way to define C functions from ruby that return a C type?

--
Konrad Meyer <konrad@tylerc.org> http://konrad.sobertil...

Nobuyoshi Nakada

9/22/2007 8:49:00 AM

0

Hi,

At Sat, 22 Sep 2007 06:54:13 +0900,
Daniel Berger wrote in [ruby-talk:270261]:
> + if RUBY_PLATFORM.match('mswin')
> + raise if status != 0
> + else
> + raise if status.exitstatus != 0
> + end

I'm curious why win32/process doesn't return Process::Status.

--
Nobu Nakada

Daniel Berger

9/22/2007 11:32:00 AM

0

Nobuyoshi Nakada wrote:
> Hi,
>
> At Sat, 22 Sep 2007 06:54:13 +0900,
> Daniel Berger wrote in [ruby-talk:270261]:
>> + if RUBY_PLATFORM.match('mswin')
>> + raise if status != 0
>> + else
>> + raise if status.exitstatus != 0
>> + end
>
> I'm curious why win32/process doesn't return Process::Status.

We had to reimplement waitpid and waitpid2 because of our custom fork
implementation. But, we weren't sure how to set $? manually to a
Process::Status object in pure Ruby. Do you have any suggestions?

Thanks,

Dan




Joel VanderWerf

9/22/2007 7:09:00 PM

0

Michael Neumann wrote:
> Hi all,
>
> I am proud to announce my latest project called CplusRuby.
> Below I pasted it's README for further explanation.
> Alternatively read the following blog article:
>
> http://www.ntecs.de/blog/articles/2007/09/21/cplusruby-gluing-...
>
> ----------------------------------------------
> CplusRuby - Glue C and Ruby together (OO-like)
> ----------------------------------------------

It's been done, but I'm glad to see it done again and probably with new
ideas :)

For comparison:

require 'cgen/cshadow' # from cgen on RAA

class NeuralEntity
include CShadow
attr_accessor :id
end

class Neuron < NeuralEntity
shadow_attr_accessor :potential => "double potential"
shadow_attr_accessor :last_spike_time => "double last_spike_time"
shadow_attr_accessor :pre_synapses => Object

define_c_method :stimulate do
arguments :at, :weight
body %{
shadow->potential += NUM2DBL(at)*NUM2DBL(weight);
}
end

def initialize
self.pre_synapses = []
end
end

NeuralEntity.commit # generate and load the shared lib

if __FILE__ == $0
n = Neuron.new
n.id = "n1"
n.potential = 1.0
n.stimulate(1.0, 2.0)
p n.potential # => 3.0
end

Cgen is middle aged, as ruby libraries go (written mostly in 2001), and
it probably isn't up to community standards in a number of ways. Still,
I've used it intensively in numerical and hybrid simulation since then.
It's the foundation for redshift, which is a DSL for simulation of
hybrid automata (networked state machines with continuous as well as
discrete dynamics).

Cgen/cshadow handles a number of issues for you:

- creating accessors (r, w, rw)
- type checking and conversion in the write accessor
- mark and free functions
- attr initialization
- persistence via marshal and yaml (or an attr may be specified
non-persistent)
- extensible attribute classes for defining new attr types, other than
the basic numeric, string, and Ruby object types
- inheritance (a subclass of a shadow class inherits the parent's shadow
attrs in its own C struct; struct may be safely cast to parent type)
- tools for managing how code is distributed among files (very important
with a large project, or else recompilation time gets painful).
- tools for managing declarations and preprocessor includes
- DSL for rb_scan_args()

This is pretty well documented, though it is in the old rd format,
rather than rdoc.

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Michael Neumann

9/22/2007 7:20:00 PM

0

Joel VanderWerf

9/22/2007 8:20:00 PM

0

Michael Neumann wrote:
> In the example you give I only see one minor difference. In CplusRuby,
> method :stimulate can be called directly from the C-side, without
> NUM2DBL conversions of Ruby-types. That's very important for my
> usage scenario.
> But I think you can do the same with cgen.

Actually, I don't think cgen has that feature.... one of the things I'll
have to er, borrow, from cplusruby. Currently the only way to do this is
to define a separate C function that the method calls.

Reading the cplusruby .c output, it looks like there is an outer
function (Neuron_call__stimulate) that accepts ruby value arguments, and
then converts them and calls an inner function (Neuron__stimulate),
which expects C-typed arguments. You could do this in cgen by using
define_c_method to define the outer function and define_c_function to
define the inner function.

I guess I was used to performing the conversion manually, so I never
added that feature as a convenience. I can see that it would be more of
a necessity than a convenience if the function needed to be called from
C as well as ruby.

The selfc->stimulate function pointer is another difference, and
necessary for the same reason, I guess. In a cshadow struct, this struct
member doesn't exist, but there is reference ("VALUE self;") back to the
original object, on which you can call methods (with the additional
friction of type conversions, if the caller is native C code).

The fact that you have pointers to functions that accept C-typed args
makes access from C easy and efficient, but it also uses a lot of space
in the struct with a pointer to each function that implements a method.
What about having a unique struct for each class that keeps these
pointers, and then the struct only needs a pointer to this "singleton"?

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Joel VanderWerf

9/22/2007 9:50:00 PM

0

Daniel Berger wrote:

> - require "#{dir}/#{mod}.so"
> + require "#{dir}/#{mod}." + CONFIG['DLEXT']
> end
>
> def self.generate_code_for_class
>
> Mostly fixes MS Windows issues, but the DLEXT bit also fixes platforms
> that don't generate .so files (OS X, HP-UX).

Why not just

> + require "#{dir}/#{mod}"

which should work if there are no stray .rb files in the dir?

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407