I’m having problems using a C++ member function with rb_protect. Here
is the code:
class Sandbox {
public:
Sandbox() {
sandbox_ = rb_funcall(rb_const_get(rb_cObject, rb_intern
(“Sandbox”)),
rb_intern(“safe”),
0);
}
virtual ~Sandbox() {
}
VALUE eval(char * code) {
int status = 0;
VALUE val = rb_protect(&Sandbox::eval_protect,
rb_str_new2(code),
&status);
if (status) { /* handle error… */ }
return val;
}
private:
VALUE eval_protect(VALUE code) {
return rb_funcall(sandbox_, rb_intern(“eval”), 1, code);
}
VALUE sandbox_;
};
The compile fails with:
test.cpp: In member function ?VALUE Sandbox::eval(char*)?:
test.cpp:18: error: cannot convert ?VALUE (Sandbox::)(VALUE)? to
?VALUE ()(VALUE)? for argument ?1? to ?VALUE rb_protect(VALUE ()
(VALUE), VALUE, int)?
$ ruby1.8 -v
ruby 1.8.5 (2006-08-06) [powerpc-darwin8.7.0]
$ g++ --version
powerpc-apple-darwin8-g+±4.0.1 (GCC) 4.0.1 (Apple Computer, Inc.
build 5341)
Copyright © 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There
is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Any ideas?
Thanks,
– Daniel
On 8/8/06, Daniel H. [email protected] wrote:
I’m having problems using a C++ member function with rb_protect. Here
is the code:
What happens if you remove the & in this line:
VALUE val = rb_protect(&Sandbox::eval_protect,
Is it possible to make Sandbox::eval_protect a static function? Because
as
an instance method, it’s prototype is not VALUE()(VALUE) but rather
something like VALUE()(Sandbox&, VALUE).
On Aug 8, 2006, at 4:45 PM, Francis C. wrote:
What happens if you remove the & in this line:
VALUE val = rb_protect(&Sandbox::eval_protect,
I get this compile error:
test.cpp: In member function ?VALUE Sandbox::eval(char*)?:
test.cpp:15: error: argument of type ?VALUE (Sandbox::)(VALUE)? does
not match ?VALUE (*)(VALUE)?
– Daniel
Any ideas?
Also, have you tried casting to a void * ?
Any ideas?
I’m not sure if it will help, but for my C++ extensions, I’ve had to
do this type of trickery:
typedef VALUE (ruby_method)(…);
when doing this:
rb_define_method(some_ruby_object, “initialize”, (ruby_method*)
&some_object_initialize, 0);
On Wed, Aug 09, 2006 at 05:57:53AM +0900, Daniel H. wrote:
not match e$B!Fe(BVALUE (*)(VALUE)e$B!Ge(B
Of course it won’t work that way, being a member function (it is given a
reference to this too…).
You’d have to do something like this (it’s been a while without writing
any
C++, so take this with a grain of salt):
class Sandbox {
public:
Sandbox() {
sandbox_ = rb_funcall(rb_const_get(rb_cObject,
rb_intern(“Sandbox”)),
rb_intern(“safe”),
0);
}
virtual ~Sandbox() {
}
VALUE eval(char * code) {
int status = 0;
VALUE args[2];
args[0] = (VALUE)this;
args[1] = rb_str_new2(code);
VALUE val = rb_protect(&call_eval_protect, (VALUE)args,
&status);
if (status) { /* handle error… */ }
return val;
}
private:
static VALUE call_eval_protect(VALUE args) {
Sandbox *me = ((Sanbox *)args)[0];
VALUE code = ((VALUE *)args)[1];
return rb_funcall(me->sandbox_, rb_intern(“eval”), 1, code);
}
VALUE sandbox_;
};
On Wed, 2006-08-09 at 06:03 +0900, Francis C. wrote:
Is it possible to make Sandbox::eval_protect a static function? Because as
an instance method, it’s prototype is not VALUE()(VALUE) but rather
something like VALUE()(Sandbox&, VALUE).
Specifically, VALUE (Sandbox::)(VALUE). Pointers to non-static methods
are actually a totally separate family of types to function pointers and
cannot be called without first using the . or ->* operators to “bind”
them. This is similar to the difference between UnboundMethod and
Proc/Method in Ruby.
-mental
On Aug 8, 2006, at 5:34 PM, Mauricio F. wrote:
Of course it won’t work that way, being a member function (it is
given a
reference to this too…).
You’d have to do something like this (it’s been a while without
writing any
C++, so take this with a grain of salt):
Thanks, I ended up with something similar.
class Sandbox
{
public:
Sandbox() {
sandbox_ = rb_funcall(rb_const_get(rb_cObject, rb_intern
(“Sandbox”)),
rb_intern(“safe”),
0);
}
virtual ~Sandbox() { }
VALUE eval(char * code) {
int status = 0;
VALUE args[2];
args[0] = reinterpret_cast(this);
args[1] = rb_str_new2(code);
VALUE val = rb_protect(eval_protect,
reinterpret_cast(args),
&status);
if (status) { }
return val;
}
VALUE & sandbox() {
return sandbox_;
}
private:
VALUE sandbox_;
static VALUE eval_protect(VALUE data) {
VALUE *args = reinterpret_cast<VALUE *>(data);
return rb_funcall(reinterpret_cast<Sandbox *>(args[0])-
sandbox(),
rb_intern(“eval”),
1,
args[1]);
}
};
– Daniel