Problem trying to use varargs in private function within C extension

D

Daniel Berger

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
 
P

Patrick Hurley

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
 
D

Daniel Berger

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
 
D

Douglas Wells

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

Patrick Hurley

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

Regards,

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
 

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,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top