Jiminion
Jiminion

Reputation: 5168

Passing variables to another variadic function [Experts Edition]

I need to write a stub for an existing variadic function within a dll. So I do what is nominally suggested:

myPyArg_ParseTuple = (void *)GetProcAddress(dll, "PyArg_ParseTuple");

int PyArg_ParseTuple(PyObject *inp1, const char *inp2, ...)
{
    int ret = 0;
    static va_list args;
    va_start(args, inp2);
    ret = myPyArg_ParseTuple(inp1, inp2, args);
    va_end(args);
    return ret;
}

All's fine, right? Well, no. Because it turns out the outside code that myPyArg_ParseTuple points to does the same thing:

[Source code of call in the .dll]

PyArg_ParseTuple(PyObject *args, const char *format, ...)
{
    int retval;
    va_list va;

    va_start(va, format);
    retval = vgetargs1(args, format, &va, 0);
    va_end(va);
    return retval;
}

So, that trick is something one cannot do twice in a row. So I am stuck. The second input is a format string, so one could easily determine the number of arguments based on the length of the string. So, could I access the variable inputs all as voids and then pass them onto separate calls, based on the number of arguments. I could use a switch based on number of arguments and then call myPyArg_ParseTuple(inp1, inp2, arg1), myPyArg_ParseTuple(inp1, inp2, arg1, arg2), etc.

It is unclear to me how to access the inputs as voids or if I can even do that.

Upvotes: 0

Views: 146

Answers (1)

rici
rici

Reputation: 241931

There is no platform-independent way to wrap variadic functions because C doesn't have a facility to forward variadic arguments without creating a va_list.

That's why variadic library functions are usually wrappers around functions which take a va_list. The Python API, for example, includes PyArg_VaParse, which you can call with a va_list. It also happens to be the implementation of PyArg_ArgParse.

[My added edit] While not a general solution, the specific solution is to instead access the PyArg_VaParse function from the DLL and pass the stub inputs into that. Then the stubs work as specified and can have the same names as the nominal functions they are mirroring.

Upvotes: 1

Related Questions