Problem trying to use varargs in private function within C extension

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

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

In article <1174230439.978761.157660@b75g2000hsg.googlegroups.com>,
"Daniel Berger" <djberg96@gmail.com> 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 Hurley's correction (in
<554ac39c0703180901u6db598dch277233129e509b79@mail.gmail.com>):

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;
}

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:

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

#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;
}

Dan

- dmw

···

--
. Douglas Wells . Connection Technologies .
. Internet: -sp9804- -at - contek.com- .

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

Regards,

Dan

···

On Mar 18, 10:01 am, "Patrick Hurley" <phur...@gmail.com> wrote:

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

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

···

On 3/18/07, Daniel Berger <djberg96@gmail.com> wrote:

On Mar 18, 10:01 am, "Patrick Hurley" <phur...@gmail.com> wrote:
> 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

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

Regards,

Dan