How to pass a va_list to a function with ellipsis (...)? 
Author Message
 How to pass a va_list to a function with ellipsis (...)?

I would like to write a wrapper for a function with optional arguments
which is declared as:
void FuncA(int line, char *file, char *fmt, ...);

My wrapper function should do something like this:
void MyFunc(char *fmt, ...)
{
  va_list vargs;
  va_start(vargs, b);
  FuncA(__LINE__, __FILE__, fmt, vargs);
  va_end(vargs);

Quote:
}

This code actually does NOT work!

How can I pass the variable argument list (vargs) to FuncA?

Thanks,
  Martin



Mon, 04 Apr 2005 17:40:13 GMT  
 How to pass a va_list to a function with ellipsis (...)?

Quote:

> void FuncA(int line, char *file, char *fmt, ...);

Have FuncA expect a va_list object instead of ... .

Quote:
>   va_list vargs;
>   va_start(vargs, b);
>   FuncA(__LINE__, __FILE__, fmt, vargs);
>   va_end(vargs);

Otherwise, that seems fine.

Bill, argy bargy.

--
 Hey there, write a robot to play Gomoku -
       http://www.bacchae.co.uk/tourk/gomoku.html
                                (I still have some 8" disks for sale)



Mon, 04 Apr 2005 17:48:50 GMT  
 How to pass a va_list to a function with ellipsis (...)?

Quote:


> > void FuncA(int line, char *file, char *fmt, ...);

> Have FuncA expect a va_list object instead of ... .

> >   va_list vargs;
> >   va_start(vargs, b);
> >   FuncA(__LINE__, __FILE__, fmt, vargs);
> >   va_end(vargs);

> Otherwise, that seems fine.

Not quite.

va_start(vargs, b) should be va_start(vargs, fmt)

--

"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton



Mon, 04 Apr 2005 18:47:54 GMT  
 How to pass a va_list to a function with ellipsis (...)?

Quote:
> I would like to write a wrapper for a function with optional arguments
> which is declared as:
> void FuncA(int line, char *file, char *fmt, ...);

> My wrapper function should do something like this:
> void MyFunc(char *fmt, ...)
> {
>   va_list vargs;
>   va_start(vargs, b);
>   FuncA(__LINE__, __FILE__, fmt, vargs);
>   va_end(vargs);
> }

> This code actually does NOT work!

> How can I pass the variable argument list (vargs) to FuncA?

You'ld either have to make FuncA expect a va_list as the fourth
parameter or FuncA will have to know that a va_list is passed in
the ellipsis, which would be rather odd.

OTOH, you may probably want to use a macro instead of a function
for wrapping around this function with the variable parameter
list, as otherwise __LINE__ and __FILE__ will always be the ones
in MyFunc and not what you probably intended to have, of the
calling function.

with C99:
#define MYFUNC(fmt, ...) \
  do { \
    FuncA(__LINE__, __FILE__, fmt, __VA_ARGS__); \
  } while(0)

if your compiler doesn't conform to C99 yet you'll have to use
some trick like:

#define MYFUNC(x) \
  do { \
    FuncLineFile(__LINE__, __FILE__); \
    FuncMsg x ; \
  } while(0)

Where FuncA needs to be split into two functions, one that
applies the work to line and file and the other that does
the rest of the message. MYFUNC than needs to be "called"
like:

  MYFUNC(("print an int %d\n", 12));

note the double parans , where the innermost will be passed
as the parameter of MYFUNC and inserted where this is used
in the macro.

OTOH many compilers provide an extension to allow for macros with
variable argument list.

--

"LISP  is worth learning for  the profound enlightenment  experience
you will have when you finally get it; that experience will make you
a better programmer for the rest of your days."   -- Eric S. Raymond



Mon, 04 Apr 2005 19:54:35 GMT  
 How to pass a va_list to a function with ellipsis (...)?

Quote:


> > > void FuncA(int line, char *file, char *fmt, ...);

> > Have FuncA expect a va_list object instead of ... .

> > >   va_list vargs;
> > >   va_start(vargs, b);
> > >   FuncA(__LINE__, __FILE__, fmt, vargs);
> > >   va_end(vargs);

> > Otherwise, that seems fine.

> Not quite.

> va_start(vargs, b) should be va_start(vargs, fmt)

Not quite, va_list may be defined as an array. To compensate, you should
pass (and subsequently expect) a pointer to va_list instead.

--
Peter



Mon, 04 Apr 2005 20:17:18 GMT  
 How to pass a va_list to a function with ellipsis (...)?

Quote:
> I would like to write a wrapper for a function with optional arguments
> which is declared as:
> void FuncA(int line, char *file, char *fmt, ...);

> My wrapper function should do something like this:
> void MyFunc(char *fmt, ...)
> {
>   va_list vargs;
>   va_start(vargs, b);
>   FuncA(__LINE__, __FILE__, fmt, vargs);

This will pass the same filename and line number each time you realise?!

Quote:
>   va_end(vargs);
> }

> This code actually does NOT work!

> How can I pass the variable argument list (vargs) to FuncA?

You can't. Either make FuncA accept an explicit va_list:

  void FuncA(int, const char *, const char *, va_list);

...or pass a pointer to one instead...

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

  void MyFunc(const char *, ...);
  void FuncA(const char *, ...);

  void MyFunc(const char *fmt, ...)
  {
    va_list vargs;
    va_start(vargs, fmt);
    FuncA(fmt, &vargs);
    va_end(vargs);
  }

  void FuncA(const char *fmt, ...)
  {
    va_list vargs;
    va_list *vargsparam;

    va_start(vargs, fmt);
    vargsparam = va_arg(vargs, va_list *);
    vprintf(fmt, *vargsparam);
    va_end(vargs);
  }

  int main()
  {
    MyFunc("%s %d\n", "The answer is...", 42);
    return 0;
  }

--
Peter



Mon, 04 Apr 2005 20:17:19 GMT  
 How to pass a va_list to a function with ellipsis (...)?
(Passing a va_list object to a function)

Quote:
> Not quite, va_list may be defined as an array. To compensate, you should
> pass (and subsequently expect) a pointer to va_list instead.

Are you sure? vfprintf seems to get on fine recieveing a copy of a va_list
object without any intermediate pointers.

Maybe vfprintf is special, being a standard library function.

Bill, magic.

--
 Hey there, write a robot to play Gomoku -
       http://www.bacchae.co.uk/tourk/gomoku.html
                                (I still have some 8" disks for sale)



Mon, 04 Apr 2005 21:04:17 GMT  
 How to pass a va_list to a function with ellipsis (...)?

Quote:
> (Passing a va_list object to a function)

> > Not quite, va_list may be defined as an array. To compensate, you should
> > pass (and subsequently expect) a pointer to va_list instead.

> Are you sure? vfprintf seems to get on fine recieveing a copy of a va_list
> object without any intermediate pointers.

> Maybe vfprintf is special, being a standard library function.

No, it's not special. :-) My comment was about passing a va_list object as
one of the "extra" arguments to a /variadic/ function. When declared
explicitly in the prototype, passing a va_list argument is possible whether
it's an array or not...

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

  void FuncA(const char *fmt, va_list vargs /*, ... */)
  {
    vprintf(fmt, vargs);
  }

  void MyFunc(const char *fmt, ...)
  {
    va_list vargs;
    va_start(vargs, fmt);
    FuncA(fmt, vargs);
    va_end(vargs);
  }

  int main()
  {
    MyFunc("%s %d\n", "The answer is...", 42);
    return 0;
  }

--
Peter



Tue, 05 Apr 2005 05:40:33 GMT  
 How to pass a va_list to a function with ellipsis (...)?

Quote:



> > I would like to write a wrapper for a function with optional arguments
> > which is declared as:
> > void FuncA(int line, char *file, char *fmt, ...);

> > My wrapper function should do something like this:
> > void MyFunc(char *fmt, ...)
> > {
> >   va_list vargs;
> >   va_start(vargs, b);
> >   FuncA(__LINE__, __FILE__, fmt, vargs);

> This will pass the same filename and line number each time you realise?!

> >   va_end(vargs);
> > }

> > This code actually does NOT work!

> > How can I pass the variable argument list (vargs) to FuncA?

> You can't. Either make FuncA accept an explicit va_list:

>   void FuncA(int, const char *, const char *, va_list);

> ...or pass a pointer to one instead...

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

>   void MyFunc(const char *, ...);
>   void FuncA(const char *, ...);

>   void MyFunc(const char *fmt, ...)
>   {
>     va_list vargs;
>     va_start(vargs, fmt);
>     FuncA(fmt, &vargs);
>     va_end(vargs);
>   }

>   void FuncA(const char *fmt, ...)
>   {
>     va_list vargs;
>     va_list *vargsparam;

>     va_start(vargs, fmt);
>     vargsparam = va_arg(vargs, va_list *);
>     vprintf(fmt, *vargsparam);
>     va_end(vargs);
>   }

>   int main()
>   {
>     MyFunc("%s %d\n", "The answer is...", 42);
>     return 0;
>   }

Thanks for your help, but one main problem is, that FuncA is from a
library where I don't have the source and therefore can't change the
declaration nor split the function into two.
So, I have to live with the "..." argument!!

As I understood, there is NO way to pass from a va_list argument to
the ellipsis (...) argument.

As some of you already found out, I did a copy/paste error in my first
post.
The va_start macro should be:
   va_start(vargs, fmt);
About the meaning or sense of the usage, like in MyFunc, calling
FuncA(__LINE__, __FILE__, ...)
I didn't care, as it was just an example. In reality, I call a
different function with different arguments.



Tue, 05 Apr 2005 06:06:54 GMT  
 How to pass a va_list to a function with ellipsis (...)?

Quote:

> Thanks for your help, but one main problem is, that FuncA is from a
> library where I don't have the source and therefore can't change the
> declaration nor split the function into two.

Does it supply a vFuncA function?

There's little you can do to resolve this without delving into the world of
undefined behaviour.

How important is portability to you?

Bill, does function calls in assembler.

--
 Hey there, write a robot to play Gomoku -
       http://www.bacchae.co.uk/tourk/gomoku.html
                                (I still have some 8" disks for sale)



Tue, 05 Apr 2005 06:40:09 GMT  
 How to pass a va_list to a function with ellipsis (...)?

Quote:


> > Thanks for your help, but one main problem is, that FuncA is from a
> > library where I don't have the source and therefore can't change the
> > declaration nor split the function into two.

> Does it supply a vFuncA function?

> There's little you can do to resolve this without delving into the world of
> undefined behaviour.

> How important is portability to you?

> Bill, does function calls in assembler.

There is NO vFuncA function !!

Probably we could do some things in assembler to push the arguments on
the stack, but this might be a problem if we will move from x86 based
CPUs to others. Actually, we are developing under Windows x86 based
systems, but we never know, if one day we need to port the code on a
Mac or any Unix system.

I prefer portability on "one time solutions".

--
Martin



Tue, 05 Apr 2005 16:49:43 GMT  
 How to pass a va_list to a function with ellipsis (...)?

Quote:


>> > Thanks for your help, but one main problem is, that FuncA is from a
>> > library where I don't have the source and therefore can't change the
>> > declaration nor split the function into two.

>> Does it supply a vFuncA function?

>> There's little you can do to resolve this without delving into the world of
>> undefined behaviour.

>> How important is portability to you?

>> Bill, does function calls in assembler.

> There is NO vFuncA function !!

> Probably we could do some things in assembler to push the arguments on
> the stack, but this might be a problem if we will move from x86 based
> CPUs to others. Actually, we are developing under Windows x86 based
> systems, but we never know, if one day we need to port the code on a
> Mac or any Unix system.

> I prefer portability on "one time solutions".

As I explained in another posting in this thread, about the only
sollution you have is to use variadic macros. But these were
introduced only with C99, so you may have to use some extension
of your compiler and surround that with "conditional inclusion"
preprocessing statments to make you recognize this when you
change the compiler or environment.

I've something like this in my zcdebug.h:

#if __STDC_VERSION__ >= 199901L
/* C99-compliant compiler */
#define zcdbg(...) do { zc_log ( __FILE__ , __LINE__ , __VA_ARGS__ ) ; } while(0)

#else
/* no variadic macros in this std-C version */

#ifdef __GNUC__
/* gcc has an extension */
#define zcdbg(args...) do { zc_log ( __FILE__ , __LINE__ , ##args ) ; } while(0)

#else
/* No way to handle this */
#error Cannot pass variable argument lists to macros

#endif

#endif

And when I have to port it to a compiler that doesn't conform to
C99 yet, and is not gcc I'ld add whatever this compiler allowed
to do or the debugging feature would have to go for that certain
implementation.
--

"LISP  is worth learning for  the profound enlightenment  experience
you will have when you finally get it; that experience will make you
a better programmer for the rest of your days."   -- Eric S. Raymond



Tue, 05 Apr 2005 17:15:50 GMT  
 How to pass a va_list to a function with ellipsis (...)?

Quote:

> There is NO vFuncA function !!

Right, someone elsethread suggested C99/gcc preprocessor extensions. If
this is inappropiate, read on.

FuncA takes a format string, which your function takes and passes on. How
many possible formats are there? (And is this a printf style format?)

     if (fmt_match(fmt,""))   { FuncA(fmt); }
else if (fmt_match(fmt,"s"))  { FuncA(fmt,va_arg(va,char*)); }
else if (fmt_match(fmt,"i"))  { FuncA(fmt,va_arg(va,int)); }
else if (fmt_match(fmt,"si")) { char* a1=va_arg(va,char*);
                                 FuncA(fmt,a1,va_arg(va,int)); }
else if (fmt_match(fmt,"is")) { int a1=va_arg(va,int);
                                 FuncA(fmt,a1,va_arg(va,char*)); }

and so on. Writing fmt_match() is left as an exercise for the reader. Only
identifying types is important, so if this is a printf-esque format string,
%x, %d and %c would all match 'i' on the list.

Devising a better algorithm than checking the string for each format every
time is also left as an exercise to the reader.

Remeber, "sifississsif" will need an else if, as well "sifississsii". You
may wish to consider automating the process of code generation to generate
an else if for each permutation, up to a reasonable limit.

(I've done printfs with twenty % insertions, so be warned.)

Frankly, I would delve into a little assembly to construct the stack for
FuncA to be called. If you make the assembly pluggable behind a simple
abstraction layer, you would only have to re-write this smallpart if you
ever come to port the code.

Bill, doomed, we're all doomed I tell you.



Tue, 05 Apr 2005 17:45:24 GMT  
 How to pass a va_list to a function with ellipsis (...)?

I had a similar problem. In our project we are simulating on Windows
using Visual C++, and compiling for target using gcc. Logging is
extensive, but we can log by logging units.

On Gnu (with variadic args) the log macro looks like this:

#define LOG_INFO(unit, format, args...) \
   do { \
      if (Log::instance()->isLoggingEnabled(unit, Log::NORMAL_LVL)) { \
         Log::instance()->logAlways(__FILE__, __LINE__, Log::INFO_LOG,
         format, ## args);\
      }\
   } while (0)

This way we never sprintf the log string unnecessarily.

On Windows we had to get past this somehow, but we still wanted to use
the same LOG_INFO(unit, format, args...) macro. The way we solved it was
this ugly baby:

#define LOG_INFO \
   Log::instance()->getTmpLog(__FILE__, __LINE__, Log::INFO_LOG,
   Log::NORMAL_LVL)->log

Letting our Log class have a number of TmpLog (bad name, I know)
instances in an array and return a new instance for each call:

TmpLog * Log::getTmpLog(const char * file, int line, TYPE type,
LEVEL level)
{
    TmpLog * l = cTmpLogs[cCurrentTmpLogIx++ % NUM_TMP_LOGS];
    l->setInfo(file, line, level, type);
    cCurrentTmpLogIx %= NUM_TMP_LOGS;
    return l;

Quote:
}

Perhaps this somewhat awkward solution could help you?

   /Anders

--
Posted via http://dbforums.com



Sun, 17 Apr 2005 00:36:00 GMT  
 
 [ 14 post ] 

 Relevant Pages 

1. va_list passed by value/reference

2. Portable to pass va_list (stdarg.h) variables?

3. Passing va_list to subroutine?

4. a va_list in a va_list

5. calling unmanaged function with variable list of arguments (ellipses) failed

6. ELLIPSES IN C FUNCTIONS

7. Passing "callback" function to a function

8. passing a function to function.

9. Passing functions to functions?

10. Pointer to function passed to varargs function

11. HELP:Passing functions to functions(!)

12. Novice: Passing a function pointer to a function

 

 
Powered by phpBB® Forum Software