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
···
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.