Using C++ Member Function with rb_protect

D

Daniel Harple

I'm having problems using a C++ member function with rb_protect. Here =20=

is the code:

class Sandbox {
public:
Sandbox() {
sandbox_ =3D rb_funcall(rb_const_get(rb_cObject, rb_intern=20
("Sandbox")),
rb_intern("safe"),
0);
}
virtual ~Sandbox() {
}
VALUE eval(char * code) {
int status =3D 0;
VALUE val =3D 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 =91VALUE Sandbox::eval(char*)=92:
test.cpp:18: error: cannot convert =91VALUE (Sandbox::*)(VALUE)=92 to =20=

=91VALUE (*)(VALUE)=92 for argument =911=92 to =91VALUE rb_protect(VALUE =
(*)=20
(VALUE), VALUE, int*)=92

$ 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. =20
build 5341)
Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There =20
is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR =20
PURPOSE.

Any ideas?

Thanks,
-- Daniel
 
D

Daniel Harple

What happens if you remove the & in this line:

VALUE val =3D rb_protect(&Sandbox::eval_protect,

I get this compile error:

test.cpp: In member function =91VALUE Sandbox::eval(char*)=92:
test.cpp:15: error: argument of type =91VALUE (Sandbox::)(VALUE)=92 does =
=20
not match =91VALUE (*)(VALUE)=92

-- Daniel
 
C

Caleb Tennis

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);
 
M

Mauricio Fernandez

I get this compile error:

test.cpp: In member function $B!F(BVALUE Sandbox::eval(char*)$B!G(B:
test.cpp:15: error: argument of type $B!F(BVALUE (Sandbox::)(VALUE)$B!G(B does
not match $B!F(BVALUE (*)(VALUE)$B!G(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_;
};
 
D

Daniel Harple

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<VALUE>(this);
args[1] = rb_str_new2(code);
VALUE val = rb_protect(eval_protect,
reinterpret_cast<VALUE>(args),
&status);
if (status) { }
return val;
}

VALUE & sandbox() {
return sandbox_;
}
private:
VALUE sandbox_;
static VALUE eval_protect(VALUE data) {
VALUE *args = reinterpret_cast said:
sandbox(),
rb_intern("eval"),
1,
args[1]);
}
};

-- Daniel
 
M

MenTaLguY

--=-KERL4m3EWNClx+pIgPy5
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

Is it possible to make Sandbox::eval_protect a static function? Because a= s
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

--=-KERL4m3EWNClx+pIgPy5
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (GNU/Linux)

iD8DBQBE2ijuSuZBmZzm14ERAhQHAJ9lJ0mR7jl4gDNq7qbMQffr61x/tgCePWds
CBB+uQ4arp3fm6kpweoZBoY=
=HybC
-----END PGP SIGNATURE-----

--=-KERL4m3EWNClx+pIgPy5--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,209
Messages
2,571,088
Members
47,687
Latest member
IngridXxj

Latest Threads

Top