Use a core C function not included in intern.h

S

Shinku Fag

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

Tim Pease

Hello.
=20
I trying to make a function with C extension for 1.8.7 that should use
functions defined in Ruby such as
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
to extension source or intern.h then I get
/usr/lib/ruby/gems/1.8/gems/rmtools-1.0.0/lib/rmtools.so: undefined =
symbol: eval
=20
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?
=20

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=
 
T

Tim Pease

=20
On Jun 3, 2010, at 6:48 PM, Shinku Fag wrote:
=20
/usr/lib/ruby/gems/1.8/gems/rmtools-1.0.0/lib/rmtools.so: undefined =
symbol: eval
=20
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.
=20
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.

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
 
M

Marvin Gülker

Tim said:
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 Programs 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
 
S

Shinku Fag

Tim said:
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.
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.
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?
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,130
Latest member
MitchellTe
Top