Question

I rm writing a C++ extension for Ruby, and am trying to extract a Ruby string object out of a Ruby array object, and convert it to a C/C++ string object.

I have foo.cpp:

#include <iostream>
#include <ruby.h>

VALUE bar_func(VALUE self, VALUE ary){
    std::string s = StringValuePtr(rb_ary_entry(ary, 0));
    ...
    return 0;
}

extern "C" VALUE rb_cFoo;
VALUE rb_cFoo;
extern "C" void Init_foo(){
    rb_cFoo = rb_define_class("Foo", rb_cObject);
    rb_define_singleton_method(rb_cFoo, "bar", RUBY_METHOD_FUNC(bar_func), 1);
}

and test.rb:

require "foo"
Foo.bar(["Hello World!"])

When I try to compile foo.cpp, the compiler returns an error saying something like "a single term & operand needs left side value" (not exact message. translated from an error message given in another natural lauguage). It's regarding my usage of StringValuePtr. What am I doing wrong, and how can it be fixed?

Was it helpful?

Solution

First of all, StringValuePtr does not return a null-terminated C string suitable for the assignment operator. You should use the StringValueCStr macro, which also takes a VALUE as parameter.

StringValueCStr is defined as follows:

#define StringValueCStr(v) rb_string_value_cstr(&(v))

The rb_string_value_cstr function signature is:

char * rb_string_value_cstr(volatile VALUE *ptr)

After macro expansion, your code should look like this:

std::string s = rb_string_value_cstr(&rb_ary_entry(ary, 0));

Your code doesn't look wrong to me. Try putting each part in separate lines to see if you can narrow down the origin of the error:

VALUE entry = rb_ary_entry(ary, 0);
char * c_str = StringValueCStr(entry);
std::string str = c_str;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top