[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Problem trying to use varargs in private function within C extension

Daniel Berger

3/18/2007 3:07:00 PM

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

4 Answers

Patrick Hurley

3/18/2007 4:02:00 PM

0

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

Daniel Berger

3/18/2007 10:11:00 PM

0

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

see

3/18/2007 11:36:00 PM

0

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

Patrick Hurley

3/18/2007 11:50:00 PM

0

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

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