# Using C++ Member Function with rb\_protect

**URL:** <https://www.ruby-forum.com/t/using-c-member-function-with-rb-protect/101964>\
**Category:** Ruby\
**Created:** [August 8, 2006, 10:33pm UTC](https://www.ruby-forum.com/t/using-c-member-function-with-rb-protect/101964 "2006-08-08T22:33:38Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![agnathan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/919ad9/32.png) [@agnathan](https://www.ruby-forum.com/u/agnathan)\
**Post date:** [August 8, 2006, 10:33pm UTC](https://www.ruby-forum.com/t/using-c-member-function-with-rb-protect/101964/1 "2006-08-08T22:33:38Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![agnathan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/919ad9/32.png) [@agnathan](https://www.ruby-forum.com/u/agnathan)\
**Post date:** [August 8, 2006, 10:48pm UTC](https://www.ruby-forum.com/t/using-c-member-function-with-rb-protect/101964/2 "2006-08-08T22:48:40Z")

</div>

On 8/8/06, Daniel H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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,

---

<div class="post-metadata">

**Author:** ![agnathan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/919ad9/32.png) [@agnathan](https://www.ruby-forum.com/u/agnathan)\
**Post date:** [August 8, 2006, 11:06pm UTC](https://www.ruby-forum.com/t/using-c-member-function-with-rb-protect/101964/3 "2006-08-08T23:06:41Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![agnathan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/919ad9/32.png) [@agnathan](https://www.ruby-forum.com/u/agnathan)\
**Post date:** [August 8, 2006, 11:00pm UTC](https://www.ruby-forum.com/t/using-c-member-function-with-rb-protect/101964/4 "2006-08-08T23:00:40Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![agnathan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/919ad9/32.png) [@agnathan](https://www.ruby-forum.com/u/agnathan)\
**Post date:** [August 8, 2006, 11:30pm UTC](https://www.ruby-forum.com/t/using-c-member-function-with-rb-protect/101964/5 "2006-08-08T23:30:42Z")

</div>

> Any ideas?

Also, have you tried casting to a void \* ?

---

<div class="post-metadata">

**Author:** ![agnathan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/919ad9/32.png) [@agnathan](https://www.ruby-forum.com/u/agnathan)\
**Post date:** [August 8, 2006, 11:30pm UTC](https://www.ruby-forum.com/t/using-c-member-function-with-rb-protect/101964/6 "2006-08-08T23:30:42Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![agnathan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/919ad9/32.png) [@agnathan](https://www.ruby-forum.com/u/agnathan)\
**Post date:** [August 8, 2006, 11:36pm UTC](https://www.ruby-forum.com/t/using-c-member-function-with-rb-protect/101964/7 "2006-08-08T23:36:43Z")

</div>

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\_;  
};

---

<div class="post-metadata">

**Author:** ![agnathan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/919ad9/32.png) [@agnathan](https://www.ruby-forum.com/u/agnathan)\
**Post date:** [August 9, 2006, 8:29pm UTC](https://www.ruby-forum.com/t/using-c-member-function-with-rb-protect/101964/8 "2006-08-09T20:29:18Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![agnathan](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/919ad9/32.png) [@agnathan](https://www.ruby-forum.com/u/agnathan)\
**Post date:** [August 9, 2006, 12:00am UTC](https://www.ruby-forum.com/t/using-c-member-function-with-rb-protect/101964/9 "2006-08-09T00:00:43Z")

</div>

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
