General question about args (embedded code)

There is a lot of function in the Ruby C API that takes the

VALUE (*body)(), VALUE args

combo parameters (such as rb_protect, or rb_rescue), and I don’t
understand how I should pass multiple arguments with such declaration.
For example, how should I rb_protect a function call like this?

rb_const_get( rb_cObject, rb_intern( "Foo" ) );

I saw other source cde like this:

VALUE args[2];
args[0] = rb_cObject;
args[1] = rb_intern( "Foo" );

rb_protect( rb_const_get, args, &result );

But this kind of code doesn’t works (and just don’t make sense for me
after what I read from eval.c, but maybe I’m missing something).

Thankx for helping,
Ben.

Hi,

···

In message “General question about args (embedded code)” on 03/02/25, Ben Thomas ben.thomas@wickedstudios.com writes:

I saw other source cde like this:

VALUE args[2];
args[0] = rb_cObject;
args[1] = rb_intern( “Foo” );

rb_protect( rb_const_get, args, &result );

But this kind of code doesn’t works (and just don’t make sense for me
after what I read from eval.c, but maybe I’m missing something).

“doesn’t work” has very little information. Describe how it didn’t
work; in another words, what did you expect and what did you get?

						matz.

Ben Thomas wrote:

There is a lot of function in the Ruby C API that takes the

VALUE (*body)(), VALUE args

combo parameters (such as rb_protect, or rb_rescue), and I don’t
understand how I should pass multiple arguments with such declaration.
For example, how should I rb_protect a function call like this?

rb_const_get( rb_cObject, rb_intern( "Foo" ) );

I saw other source cde like this:

VALUE args[2];
args[0] = rb_cObject;
args[1] = rb_intern( "Foo" );

rb_protect( rb_const_get, args, &result );

But this kind of code doesn’t works (and just don’t make sense for me
after what I read from eval.c, but maybe I’m missing something).

It is very non-obvious (at first glance) how functions like
rb_rescue() and rb_protect() work.

The second argument to rb_protect() is just a pointer to “some data”,
and the contents of that data are up to you. That data pointer will be
passed as the single argument to the function you pass as the first
argument to rb_protect(), so when you write:

 rb_protect(func, data, &result);

you should understand that Ruby will execute the line:

 func(data);

For the example you described, it’s not working because the function
rb_const_get() is expecting two arguments, not one. So what to do?

This usually means you’ll need to provide a “helper” function for the
function you’re actually trying to “protect”. Still using your example
scenario, let’s cook up a helper for rb_const_get() that takes just one
argument:

 VALUE rb_const_get_helper(VALUE data)
 {
     VALUE *args = (VALUE *) data;
     return rb_const_get(args[0], args[1]);
 }

Here, we’re assuming that ‘data’ points to a C array of VALUEs, and that
array has two elements. This function just turns around and calls the
real function, rb_const_get(), with the correct number of arguments. To
activate this with rb_protect(), we can now use the original snippet you
posted:

 VALUE args[2];
 VALUE result;
 int state;

 args[0] = rb_cObject;
 args[1] = rb_intern("Foo");

 result = rb_protect(rb_const_get_wrapper, (VALUE) &args[0], &state);

Hope this helps,

Lyle

My mistake, “doesn’t work” don’t give any information at all.

When I debugged my example, the second argument is never passed to
rb_const_get function. After I read the code of rb_protect, I though it
was normal that this code doesn’t work since rb_protect only pass 1
arguments to the function it’s calling. But I’m not an expert in pure C,
so I was thinking that maybe I’m missing something, that there was a way
to pass many arguments without using helper functions…

Hope I provided enough information this time,
Ben.

Yukihiro Matsumoto wrote:

···

Hi,

In message “General question about args (embedded code)” > on 03/02/25, Ben Thomas ben.thomas@wickedstudios.com writes:

I saw other source cde like this:

VALUE args[2];
args[0] = rb_cObject;
args[1] = rb_intern( “Foo” );

rb_protect( rb_const_get, args, &result );

But this kind of code doesn’t works (and just don’t make sense for me
after what I read from eval.c, but maybe I’m missing something).

“doesn’t work” has very little information. Describe how it didn’t
work; in another words, what did you expect and what did you get?

  					matz.

Hi,

When I debugged my example, the second argument is never passed to
rb_const_get function. After I read the code of rb_protect, I though it
was normal that this code doesn’t work since rb_protect only pass 1
arguments to the function it’s calling. But I’m not an expert in pure C,
so I was thinking that maybe I’m missing something, that there was a way
to pass many arguments without using helper functions…

So you’re expecting rb_const_get() to receive two arguments. Hmm,
rb_protect() calls its function argument with single argument, you
have to unpack by yourself, i.e.

static VALUE
cget(VALUE *args)
{
return rb_const_get(args[0], (ID)args[1]);
}

void
foo()
{
VALUE args[2];
args[0] = rb_cObject;
args[1] = rb_intern(“Foo”);

  rb_protect(cget, args, &result);

}

Do you get it?

						matz.
···

In message “Re: General question about args (embedded code)” on 03/02/26, Ben Thomas ben.thomas@wickedstudios.com writes:

Yukihiro Matsumoto wrote:

Hi,

When I debugged my example, the second argument is never passed to
rb_const_get function. After I read the code of rb_protect, I though it
was normal that this code doesn’t work since rb_protect only pass 1
arguments to the function it’s calling. But I’m not an expert in pure C,
so I was thinking that maybe I’m missing something, that there was a way
to pass many arguments without using helper functions…

So you’re expecting rb_const_get() to receive two arguments. Hmm,
rb_protect() calls its function argument with single argument, you
have to unpack by yourself, i.e.

static VALUE
cget(VALUE *args)
{
return rb_const_get(args[0], (ID)args[1]);
}

void
foo()
{
VALUE args[2];
args[0] = rb_cObject;
args[1] = rb_intern(“Foo”);

  rb_protect(cget, args, &result);

}

Do you get it?

  					matz.

Yep, and it works just fine!

Thankx for the answer!
Ben.

···

In message “Re: General question about args (embedded code)” > on 03/02/26, Ben Thomas ben.thomas@wickedstudios.com writes: