Calling variadic funcs

K

keith

Someone please help me out here - I'm having a 'bad brain' day.

I have a number of C logging functions, prototyped as, say:

extern "C" {
mylog1(char *arg1, char *arg2, char *arg3);
mylog2(char *arg1, char *arg2, ...);
mylog3(char *arg1, ...);
}

What I want to do is throw a C++ wrapper around them. The first case
above is pretty trivial:

MYLOG::eek:ne(char *a1, char *a2, char *a3)
{ mylog1(a1, a2, a3); }

For the life of me I can't see how I go about passing the variadic
args for the other two cases!
 
I

Ivan Vecerina

:
: Someone please help me out here - I'm having a 'bad brain' day.
:
: I have a number of C logging functions, prototyped as, say:
:
: extern "C" {
: mylog1(char *arg1, char *arg2, char *arg3);
: mylog2(char *arg1, char *arg2, ...);
: mylog3(char *arg1, ...);
: }
:
: What I want to do is throw a C++ wrapper around them. The first case
: above is pretty trivial:
:
: MYLOG::eek:ne(char *a1, char *a2, char *a3)
: { mylog1(a1, a2, a3); }
:
: For the life of me I can't see how I go about passing the variadic
: args for the other two cases!

The variadic functions are called in the exact same way,
provided that the function's implementation expects the
corresponding number of parameters, and of the correct type:

extern "C" {
void mylog1(char *arg1, char *arg2, char *arg3);
void mylog2(char *arg1, char *arg2, ...);
void mylog3(char *arg1, ...);
}

void one(char *a1, char *a2, char *a3) { mylog1(a1, a2, a3); }
void two(char *a1, char *a2, char *a3) { mylog2(a1, a2, a3); }
void thr(char *a1, char *a2, char *a3) { mylog3(a1, a2, a3); }



-Ivan
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

Someone please help me out here - I'm having a 'bad brain' day.

I have a number of C logging functions, prototyped as, say:

extern "C" {
mylog1(char *arg1, char *arg2, char *arg3);
mylog2(char *arg1, char *arg2, ...);
mylog3(char *arg1, ...);
}

What I want to do is throw a C++ wrapper around them. The first case
above is pretty trivial:

MYLOG::eek:ne(char *a1, char *a2, char *a3)
{ mylog1(a1, a2, a3); }

For the life of me I can't see how I go about passing the variadic
args for the other two cases!

If you have a C99 compliant compiler take a look at the va_* macros in
stdarg.h. For older compilers look at varargs.h.
 
K

keith

If you have a C99 compliant compiler take a look at the va_* macros in
stdarg.h. For older compilers look at varargs.h.

I spotted those, but they appear to require that you know how many
arguments are being passed in. I suppose I can count the format
specifiers in the format string that comes in, and assume that is
equal to the number of following arguments...
 
Z

Zeppe

I spotted those, but they appear to require that you know how many
arguments are being passed in. I suppose I can count the format
specifiers in the format string that comes in, and assume that is
equal to the number of following arguments...
To be honest, I doubt that you can wrap easily a variable arguments
function as you want. There is a macro __VA_ARGS__ for the variable
arguments macro, but I'm not really sure that you can pass a variable
number of arguments to a function in a compact form with the expressive
power of the language...

Regards,

Zeppe
 
K

keith

To be honest, I doubt that you can wrap easily a variable arguments
function as you want. There is a macro __VA_ARGS__ for the variable
arguments macro, but I'm not really sure that you can pass a variable
number of arguments to a function in a compact form with the expressive
power of the language...

Well, I'm pretty sure that this isn't correct by any standard, and the
chances of it working on a different platform are probably close to
zero, because I'm relying on "..." being synonymous with a parameter
of type 'va_list', but having said all that, this works:

extern "C" {
void dprintf(enum e_dlog level, char *format, ...);
}

#include <stdarg.h>
void DLOG::log(enum e_dlog level, char *fmt, ...)
{
va_list args;
va_start(args, fmt);
dprintf(level, fmt, args);
}
 
Z

Zeppe

Well, I'm pretty sure that this isn't correct by any standard, and the
chances of it working on a different platform are probably close to
zero, because I'm relying on "..." being synonymous with a parameter
of type 'va_list', but having said all that, this works:

extern "C" {
void dprintf(enum e_dlog level, char *format, ...);
}

#include <stdarg.h>
void DLOG::log(enum e_dlog level, char *fmt, ...)
{
va_list args;
va_start(args, fmt);
dprintf(level, fmt, args);
}

Well, I have to admit that the standard is quite cryptic in this:

If access to the varying arguments is desired, the called function shall
declare an object (generally referred to as ap in this subclause) having
type va_list. The object ap may be passed as an argument to another
function; if that function invokes the va_arg macro with parameter ap,
the value of ap in the calling function is indeterminate and shall be
passed to the va_end macro prior to any further reference to ap.

I can understand that you are allowed to pass ap as an argument, but
that the function that makes use of the object ap shall invoke the
va_arg with ap, it shouldn't declare a new va_list (as dprintf in your
case does). I think your code is working just by chance, because it
happens that the arguments are aligned in the stack in the correct way
when you call the dprintf function.

Pay attention to that.

Regards,

Zeppe
 
M

Markus Schoder

Well, I'm pretty sure that this isn't correct by any standard, and the
chances of it working on a different platform are probably close to
zero, because I'm relying on "..." being synonymous with a parameter of
type 'va_list', but having said all that, this works:

extern "C" {
void dprintf(enum e_dlog level, char *format, ...); }

#include <stdarg.h>
void DLOG::log(enum e_dlog level, char *fmt, ...) {
va_list args;
va_start(args, fmt);
dprintf(level, fmt, args);
}

For printf and friends there are vprintf and such which will accept a
va_list argument. Maybe there is a vdprintf wherever dprintf came from.

You also need a va_end(args); at the end of your function.
 
R

red floyd

Erik said:
If you have a C99 compliant compiler take a look at the va_* macros in
stdarg.h. For older compilers look at varargs.h.

stdarg.h is C90, not just C99.
 

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

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,119
Latest member
IrmaNorcro
Top