Jason Roelofs
12/26/2007 11:08:00 PM
[Note: parts of this message were removed to make it a legal post.]
On Dec 25, 2007 9:44 PM, gga <GGarramuno@aol.com> wrote:
> On Dec 24, 4:02 pm, Jason Roelofs <jameskil...@gmail.com> wrote:
> > I'm using Boost right now, and have tried
> > Boost.Function and Boost.Bind to no avail (the code compiles but the
> actual
> > call causes a seg fault, I assume the memory location is voided after
> the
> > init is done, so trying to pass execution to a bad memory location, but
> I'm
> > not sure). For the record, I am trying my hand at a Boost.Ruby library.
> >
>
> Your assumption is correct. You can't do it. The functor needs to
> remain visible in memory. Also, depending on your compiler, the way C+
> + functions expect arguments may be different from what ruby expects
> in its C API (this is usually a problem with Windows' __stdcall vs.
> __fastcall, etc).
> You will also not get ANY speed benefit from using a functor, thou, so
> using it is kind of pointless.
>
>
> > I'm also wondering if there is another way to add methods to Kernel or
> > Classes outside of the rb_define_* methods. In Python you can do
> > PyObject_SetAttr(namespace, name, PyCFunction) which is effectively ("
> > namespace.name = function"). I've yet to find an equivalent in Ruby.
>
> No.
>
> class A
> def f; end
> end
>
> repeat as many times as needed. Classes are open in ruby.
> rb_define_* do just the above and is equivalent to python's adding of
> functions.
>
> Overall, as the other poster said, you should use SWIG. There's
> really no benefit to using a C++ approach to wrapping code like
> Boost.Python does. If anything, Boost.Python is much more primitive
> than what swig can do.
>
>
SWIG does not handle nested classes, a *serious* defect to what I'm trying
to do. I've looked into helping add this feature, but the amount of work
required makes it more feasible to build a better, Ruby-specific wrapper
system.
And comparing Boost.Python to SWIG really doesn't make sense. You need to
compare Boost.Python with Py++ to SWIG.
I'm going to post this to Ruby-core as well to see if I can glean any
insight from those who know the innards of Ruby.
For Ruby-core: Is the following code bit even possible or feasible, to the
best of your knowledge. Basically, I need to send a dynamically generated
function pointer to rb_define_* methods. If this is not possible, I guess I
could go with method_missing, and dispatch the call in C++ according to the
name, but man, that sounds hacky.
Anyway, here is the proto code I'm using to figure this out:
function_test.cpp:
#include "ruby.h"
#include <iostream>
#include <boost/function.hpp>
#include <boost/bind.hpp>
using namespace std;
typedef VALUE (ruby_method)(...);
struct ruby_func
{
VALUE operator()(VALUE self, VALUE args) {
cout << "In functor" << endl;
//cout << "Function called, name " << m_name << endl;
return Qnil;
}
};
ruby_func func;
boost::function2<VALUE, VALUE, VALUE> f1;
VALUE func_check(VALUE self, VALUE args) {
if (f1) {
cout << "Function object exists" << endl;
// And just to prove, call it
f1(Qnil, Qnil);
} else {
cout << "Function object does not exist" << endl;
}
return Qnil;
}
extern "C"
void Init_function_test()
{
f1 = boost::bind<VALUE>(func, _1, _2);
// Prove that boost::bind worked correctly
f1(Qnil, Qnil);
// Method created to check that the function object still exists in memory
rb_define_global_function("check_function", (ruby_method*) &func_check,
-2);
// Actual function call, this causes segfault
rb_define_global_function("do_function_test", (ruby_method*) &f1, -2);
}
test.rb:
require 'function_test'
# Proper output from extension
check_function
# Segfault
do_function_test
Thanks for your help.
Jason