Use a core C function not included in intern.h

Hello.

I trying to make a function with C extension for 1.8.7 that should use
functions defined in Ruby such as

VALUE eval(VALUE,VALUE,VALUE,const char*,int)
But functions that aren’t reflected (sorry, I don’t know how to call it
better r_r) in intern.h, seems to be unusable. If I just add string
VALUE eval _((VALUE,VALUE,VALUE,const char*,int));
to extension source or intern.h then I get
symbol lookup error: /usr/lib/ruby/gems/1.8/gems/rmtools-1.0.0/lib/rmtools.so: undefined symbol: eval

So, is there a way to use such functions in the extension without
copypasting half the eval.c (and maybe even something else) into it?

Thanks.

On Jun 3, 2010, at 6:48 PM, Shinku Fag wrote:

So, is there a way to use such functions in the extension without
copypasting half the eval.c (and maybe even something else) into it?

The “eval” method in the eval.c source file is marked as static. It
cannot be called from outside the eval.c source file. This is a feature
of the compiler/linker, and to the best of my knowledge there is no easy
way around it.

If someone with more recent C experience could chime in, it would be
appreciated. My C is a little rusty, and would love for someone to
double check my facts.

Blessings,
TwP

On Jun 4, 2010, at 9:19 AM, Tim P. wrote:

VALUE eval _((VALUE,VALUE,VALUE,const char*,int));

On second thought, use the rb_funcall method …

rb_funcall(rb_mKernel, rb_intern(“eval”), … )

That should do what you are trying to accomplish.

Blessings,
TwP

Tim P. wrote:

On Jun 4, 2010, at 9:19 AM, Tim P. wrote:

VALUE eval _((VALUE,VALUE,VALUE,const char*,int));

On second thought, use the rb_funcall method …

rb_funcall(rb_mKernel, rb_intern(“eval”), … )

That should do what you are trying to accomplish.

Blessings,
TwP

Why not directly use rb_eval_string?

From the README.EXT from 1.9.1-p378:

2.2.1 Evaluate Ruby P.s in a String

The easiest way to use Ruby’s functionality from a C program is to
evaluate the string as Ruby program. This function will do the job:

VALUE rb_eval_string(const char *str)

Evaluation is done under the current context, thus current local
variables
of the innermost method (which is defined by Ruby) can be accessed.

Note that the evaluation can raise an exception. There is a safer
function:

VALUE rb_eval_string_protect(const char *str, int *state)

It returns nil when an error occur. And *state is zero if str was
successfully evaluated, or nonzero otherwise.

Marvin

Tim P. wrote:

The “eval” method in the eval.c source file is marked as static. It
cannot be called from outside the eval.c source file. This is a feature
of the compiler/linker, and to the best of my knowledge there is no easy
way around it.
Uh-huh, thanks. Now I see. Non-static functions in sources is actually
linkable.

On second thought, use the rb_funcall method …
Yeah, sometimes it suits for C function, though, unfortunately,
necessity of rb_funcall often causes a performance penalty.

Marvin Gülker wrote:

Why not directly use rb_eval_string?
Because it uses the ruby_top_self (main:Object) instead of specific
object in context of which we want to evaluate the string. Hence, we
can’t use it to evaluate an implicit method calls as ‘count("\n")’, for
example.

v = eval(ruby_top_self, rb_str_new2(str), Qnil, 0, 0);

Well, I used rb_funcall here… What I’ve tried to do is function that
rolls the stack back to the optional frame and evaluates the src string
in the scope of that frame.

static VALUE rb_eval_frame(VALUE self, VALUE src, VALUE levv)
{
struct FRAME *frame_orig = ruby_frame;
NODE *node_orig = ruby_current_node;
VALUE val;
int lev = FIX2INT(levv);

while (lev-- > 0) {
ruby_frame = ruby_frame->prev;
if (!ruby_frame) break;
}

val = rb_funcall(self, rb_intern(“eval”), 1, src);
ruby_current_node = node_orig;
ruby_frame = frame_orig;

return val;
}

But I would fail anyway, because neither FRAME nor RNode nor SCOPE
structs don’t contain references to previous scopes. Is there any way to
get NOT current scope?