bryanedds said:
All I can find is some outdated docs with command line instructions
that don't work. Can someone please point in differenct direction?
Raw Ruby is easier than SWIG - even when you need all of SWIG's features.
Here's some of my integrational code. First, we have a super-thin wrapper
for the Ruby VALUE type, the root type of all Ruby expressions:
class
rbValue
{
public:
rbValue(VALUE nuV = Qnil):
v(nuV)
{}
rbValue(char const * gv):
v(Qnil)
{
assert(gv);
assert('$' == gv[0]); // documentation sez this is optional. We don't
agree
v = rb_gv_get(gv);
}
operator VALUE() const { return v; } // TODO deprecate me
rbValue &operator =(VALUE nuV) { v = nuV; return *this; } // TODO
deprecate me
rbValue
fetch(char const * tag)
{
return funcall("fetch", 2, rb_str_new2(tag), Qnil);
}
rbValue
fetch(int idx)
{
return funcall("fetch", 2, INT2FIX(idx), Qnil);
}
rbValue
fetch(size_t idx)
{
return funcall("fetch", 2, INT2FIX(idx), Qnil);
}
VALUE *
getPtr()
{
assert(T_ARRAY == TYPE(v));
return RARRAY(v)->ptr;
}
long
getLen()
{
assert(T_ARRAY == TYPE(v));
return RARRAY(v)->len;
}
rbValue
getAt(long idx)
{
assert(idx < getLen());
return RARRAY(v)->ptr[idx];
}
rbValue
operator[](long idx)
{
return getAt(idx);
}
bool isNil() { return Qnil == v; }
double to_f()
{
assert(T_FLOAT == TYPE(v) || T_FIXNUM == TYPE(v));
return NUM2DBL(v);
}
char const * to_s()
{
assert(T_STRING == TYPE(v));
return STR2CSTR(v);
}
rbValue
funcall (
char const * method,
int argc = 0,
VALUE arg1 = Qnil,
VALUE arg2 = Qnil,
VALUE arg3 = Qnil
)
{
return rb_funcall(v, rb_intern(method), argc, arg1, arg2, arg3);
}
rbValue
iv_get(char const * member)
{
VALUE iv = rb_iv_get(v, member);
return iv;
}
void
iv_set(char const * member, VALUE datum)
{
rb_iv_set(v, member, datum);
}
void
iv_set(char const * member, int datum)
{
iv_set(member, INT2FIX(datum));
}
private:
VALUE v;
}; // a smart wrapper for the Ruby VALUE type
You simply use it the way you think to use a Ruby value, and (like Ruby) it
will defend the actual wrapped type at runtime. Unlike Ruby, it will defend
by breaking an assertion. You might like to throw, or you might write
strongly-typed code and never break.
Read the Ruby documentation for extending to C. Extend to C-style C++, and
call a Ruby script. If it creates a global variable called $egg, you can
retrieve this variable and use it in C++ like this:
egg = rbValue("$egg");
if (egg.isNil())
return false;
out = rbValue("$out"); assert(!out.isNil());
ax = egg.iv_get("@rootAxioms").funcall("first"); assert(!ax .isNil());
And so on. The result looks like Ruby, but with extra iv_get() and funcall()
between everything. From here, writing new C++ to drive Ruby is very easy,
and converting Ruby to Ruby-style C++ is also super easy.