C Variadic Function in C ++ Shell

I am rewriting the C wrapper around the C Python API (Python 1.5), and I noticed that the Py_VaBuildValue function uses a variable number of arguments. I was wondering if I should use the same in my C ++ function shell to go to that function, or if there is more C ++ way to handle this?

I know that variable functions can be the cause of an unspeakable problem, so I would prefer to avoid using if there is a better way.

EDIT:

So here is the C code that I need to do in the C ++ function:

int Set_Global(char *modname, char *varname, char *valfmt, ... /* cval(s) */) {

    int result;
    PyObject *module, *val;                             // "modname.varname = val"
    va_list cvals;
    va_start(cvals, valfmt);                            // C args after valfmt

    module = Load_Module(modname);                      // get/load module
    if (module == NULL) 
        return -1;
    val = Py_VaBuildValue(valfmt, cvals);               // convert input to Python
    va_end(cvals);
    if (val == NULL) 
        return -1;
    result = PyObject_SetAttrString(module, varname, val); 
    Py_DECREF(val);                                     // set global module var
    return result;                                      // decref val: var owns it
}

So, I am doing the same function with std :: string instead of char *, and I want to change the ellipsis to something more than C ++, so that I can, however, go to Py_VaBuildValue inside the function.

+3
source share
2

- , ( ) valfmt, , ( , printf, ). - :

template <typename T> struct format_trait;
template <> struct format_trait<int> { static const char * format() { return "%i"; }};
template <> struct format_trait<unsigned> { static const char * format() { return "%u"; }};
... // and so on for each type you want to use

template <typename Arg1>
int Set_Global(const std::string &modname, const std::string &varname, const Arg1 &arg1)
{
    return ::Set_Global(modname.c_str(), varname.c_str(), format_trait<Arg1>::format(), arg1);
}

template <typename Arg1, typename Arg2>
int Set_Global(const std::string &modname, const std::string &varname, const Arg1 &arg1, const Arg2 &arg2)
{
    return ::Set_Global(modname.c_str(), varname.c_str(),
        std::string(format_trait<Arg1>::format()) + format_trait<Arg2>::format(),
        arg1, arg2);
}
... // Repeat up to number of argument you reasonably expect to need or use C++0x variadic templates.

, . - , , valfmt ( ) .

+3

, .

bool BuildValueCheck(const char * s, int v)
{
    if( s[0] == 'i' )
        return true;
    return false;
}
bool BuildValueCheck(const char * s, float v)
{
    if( s[0] == 'f' )
        return true;
    return false;
}
bool BuildValueCheck(const char * s, char * v)
{
    if( s[0] == 's' || s[0] == 'z' )
        return true;
    return false;
}
// and so on for each other type
template<typename t1>
PyObject *BuildValue(char * format, t1 v1)
{
     char * s = strchr(format, "ifsz...."); // Skip here all "()[]" etc
     if( !s )
         return NULL; // and print an error
     if(!BuildValueCheck(s, v1))
         return NULL; // and also print an error
     return Py_BuildValue(format, v1);
}

template<typename t1, typename t2>
PyObject *BuildValue(char * format, t1 v1, t2 v2)
{
     // Skip here all "()[]" etc
     char * s = strchr(format, "ifsz....");
     if( !s )
         return NULL;
     if(!BuildValueCheck(s, v1))
         return NULL;
     s = strchr(s+1, "ifsz....");
     if( !s )
         return NULL;
     if(!BuildValueCheck(s, v2))
         return NULL;
     return Py_BuildValue(format, v1, v2);
}
// and so on for 3,4,5 params - I doubt your program uses more
// and then replace all Py_BuildValue with BuildValue across the code, or make a #define 
+1

All Articles