Friday, February 4, 2011

How to wrap a function with variable length arguments?

I am looking to do this in C/C++.

I came across Variable Length Arguments but this suggests a solution with Python & C using libffi.

Now, if i want to wrap printf function with myprintf

i do like below:

void myprintf(char* fmt, ...)
{
    va_ list args;
    va_ start(args,fmt);
    printf(fmt,args);
    va_ end(args);
}

int _tmain(int argc, _TCHAR* argv[])
{
    int a = 9;
    int b = 10;
    char v = 'C';
    myprintf("This is a number: %d and \nthis is a character: %c and \n another number: %d\n",a, v, b);
    return 0;
}

But the results are not as expected!

This is a number: 1244780 and
this is a character: h and
another number: 29953463

any pointer where i miss??

Thanks.. Any suggestion is appreciated.

  • How do you mean a pure C/C++ solution?

    The rest parameter (...) is supported cross platform in the C runtime.

    http://msdn.microsoft.com/en-us/library/kb57fad8.aspx

  • Are you using C or C++? The next C++ version, C++0x, will support variadic templates which provide a solution to that problem.

    Another workaround can be achieved by clever operator overloading to achieve a syntax like this:

    void f(varargs va) {
        BOOST_FOREACH(varargs::iterator i, va)
            cout << *i << " ";
    }
    
    f(args = 1, 2, 3, "Hello");
    

    In order to get this to work, the class varargs has to be implemented to override operator = that returns a proxy object which, in turn, overrides operator ,. However, making this variant type safe in current C++ isn't possible as far as I know since it would have to work by type erasure.

  • I am also unsure what you mean by pure

    In C++ we use

    class Foo
    {   void Write(const char* pMsg, ...);
    };
    
    void Foo::Write( const char* pMsg, ...)
    {
        char buffer[4096];
            std::va_list arg;
            va_start(arg, pMsg);
            std::vsnprintf(buffer, 4096, pMsg, arg);
            va_end(arg);
            ...
    }
    
  • the problem is that you cannot use 'printf' with va_args. You must use vprintf if you are using variable argument lists. vprint, vsprintf, vfprintf, etc. (there are also 'safe' versions in Microsoft's C runtime that will prevent buffer overruns, etc.)

    You sample works as follows:

    void myprintf(char* fmt, ...)
    {
        va_ list args;
        va_ start(args,fmt);
        vprintf(fmt,args);
        va_ end(args);
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        int a = 9;
        int b = 10;
        char v = 'C'; 
        myprintf("This is a number: %d and \nthis is a character: %c and \n another number: %d\n",a, v, b);
        return 0;
    }
    
    From Mark
  • Reading the comments to this question was like reading my son's handwriting. The correct answer is (as Mark Allender pointed out) to use the vprintf function, not the printf function.

0 comments:

Post a Comment