Problem trying to use varargs in private function within C e

Hi all,

Ruby 1.8.6
Windows XP
VC++ 8

This simple C extension complains of “too few arguments for call” when
I try to build it. Yet, within a standalone C program it works fine.
Am I forced to use varargs.h instead of stdarg.h? If so, how do I make
this work? The varargs.h docs confuse me.

#include <ruby.h>
#include <stdarg.h>

int test(const char*, …);

/* String mandatory, encoding optional /
int test(const char
str, int encoding, …){
int total = 0;
total = encoding;

printf(“X: %s\n”, str);
printf(“Encoding: %i\n”, encoding);

return total;
}

static VALUE foo_test(VALUE self){
int total = 0;

total = test(“hello”); /* Failure! */
printf(“TOTAL: %i\n”);
return self;
}

void Init_foo(){
VALUE cFoo = rb_define_class(“Foo”, rb_cObject);
rb_define_method(cFoo, “test”, foo_test, 0);
}

And here’s the standalone C code that builds and runs fine:

#include <windows.h>
#include <stdio.h>
#include <stdarg.h>

int test(const char*, …);

int main(){
int val = 0;

val = test(“hello”, 3);
printf(“VAL: %i\n”, val);

return 0;
}

int test(const char* x, int encoding, …){
int total = 0;
total = encoding;

printf(“Encoding: %i\n”, encoding);

return total;
}

Thanks,

Dan

On Mar 18, 10:01 am, “Patrick H.” [email protected] wrote:

total = test(“hello”, 3);

Does it compile?
pth

Yes, the C code compiles either way. The Ruby code will only compile
if I provide the 2nd argument.

Regards,

Dan

Dan,

In you example pure C code you are calling test with 2 parameters in
your ruby code, only one. Your prototype has one mandatory param, and
the function actually has two. If you change:

total = test(“hello”);

to

total = test(“hello”, 3);

Does it compile?
pth

On 3/18/07, Daniel B. [email protected] wrote:

Dan

Then, my next guess is that it is the order of the prototypes and the
actual function. In the C example you have a prototype (one param),
use, definition (with two+ params). In the Ruby example you have
prototype, definition (2+ params, over rides prototype), use. Move the
init_foo, up where your main is in the stand alone example.

FYI accessing the second parameter if you do not pass it, is likely to
cause a memory exception on many platforms (depending upon call depth,
build mode, etc).

pth

In article [email protected],
“Daniel B.” [email protected] writes:

Hi all,

Ruby 1.8.6
Windows XP
VC++ 8

This simple C extension complains of “too few arguments for call” when
I try to build it. Yet, within a standalone C program it works fine.
Am I forced to use varargs.h instead of stdarg.h? If so, how do I make
this work? The varargs.h docs confuse me.

Let me add a few comments in addition to Patrick H.'s correction (in
[email protected]):

First, varargs.h will not help. In fact, you don’t even need
stdarg.h until you actually start to reference the arguments using
the appropriate macros.

Second, turn on the compiler diagnostics. Both of your programs
below are not legal C and any reasonable compiler should diagnose
the problem(s). In particular, your declarations and definitions
of “test” differ. Your declaration declares the procedure to have
one mandatory argument; your definition requires that there are
two mandatory arguments. These are inconsistent (and thus illegal).

Third, relevant to Patrick’s correction, note that your “stand-alone”
test case is not at all the same as the in-context code (the number
of arguments supplied is different).

#include <ruby.h>
#include <stdarg.h>

int test(const char*, …);

/* String mandatory, encoding optional /
int test(const char
str, int encoding, …){
int total = 0;
total = encoding;

printf(“X: %s\n”, str);
printf(“Encoding: %i\n”, encoding);

return total;
}

Running with spirit of this comment:

/* String mandatory, encoding optional /
int test(const char
x, …){
va_list ap;
int total = 0;
int encoding;

va_start (ap, x);
encoding = va_arg(ap, int);
va_end(ap);

total = encoding;

printf(“Encoding: %i\n”, encoding);

return total;
}

rb_define_method(cFoo, “test”, foo_test, 0);
}

And here’s the standalone C code that builds and runs fine:

Just because it builds and runs fine doesn’t mean that it isn’t
wrong. That mind set just leads to future problems.

printf(“VAL: %i\n”, val);
return total;
}

Dan

  • dmw