C++ C++;包装纸

C++ C++;包装纸,c++,c,variadic-functions,C++,C,Variadic Functions,我正在围绕一个C Python API(Python 1.5)重写一个C包装器,我注意到函数Py_VaBuildValue使用了可变数量的参数。我想知道我是否必须在C++函数包装器中使用相同的函数来传递这个函数,或者是否有一个C++的方法来处理这个问题? 我知道可变函数可能会导致无法形容的麻烦,所以如果有更好的方法,我宁愿避免使用 编辑: 这里是C代码,我需要做的C++函数:< /P> int Set_Global(char *modname, char *varname, char *valf

我正在围绕一个C Python API(Python 1.5)重写一个C包装器,我注意到函数Py_VaBuildValue使用了可变数量的参数。我想知道我是否必须在C++函数包装器中使用相同的函数来传递这个函数,或者是否有一个C++的方法来处理这个问题? 我知道可变函数可能会导致无法形容的麻烦,所以如果有更好的方法,我宁愿避免使用

编辑:

这里是C代码,我需要做的C++函数:< /P>
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
}

<> p> >我用STD::string代替char *做同样的函数,我想把省略号变成更像C++的东西,但是我可以把它传递到函数内的pYVAbuIdDIVE值。

< P>如果你想聪明,不要害怕一些沉重的模板魔法,应该可以生成(或按摩)
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.
模板结构格式\u特征;
模板结构格式{static const char*format(){返回“%i”;};
模板结构格式{static const char*format(){返回“%u”;};
... // 对于要使用的每种类型,依此类推
模板
int Set_Global(常量std::string和modname,常量std::string和varname,常量Arg1和Arg1)
{
return::Set_Global(modname.c_str(),varname.c_str(),format_trait::format(),arg1);
}
模板
int Set_Global(常量std::string和modname,常量std::string和varname,常量Arg1和Arg1,常量Arg2和Arg2)
{
return::Set_Global(modname.c_str(),varname.c_str(),
std::string(format_trait::format())+format_trait::format(),
arg1、arg2);
}
... // 重复多达您合理预期需要的参数数,或使用C++0x可变模板。

这是一种简单的方法,其中每个值都以默认方式格式化并组合在一起。如果您想要更复杂的内容,可以创建一个函数,该函数将获得
valfmt
字符串和正确的格式说明符(从trait中获得),并将格式字符串修复为匹配。

您可以编写模板函数来检查参数的正确性,并且不允许程序崩溃

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 
bool BuildValueCheck(const char*s,int v)
{
如果(s[0]=“i”)
返回true;
返回false;
}
布尔构建值检查(常量字符*s,浮点v)
{
如果(s[0]=='f')
返回true;
返回false;
}
布尔构建值检查(常量字符*s,字符*v)
{
如果(s[0]='s'| | s[0]='z')
返回true;
返回false;
}
//对于其他类型,等等
模板
PyObject*构建值(字符*格式,t1 v1)
{
char*s=strchr(格式为“ifsz…”);//此处跳过所有“()[]”等
如果(!s)
返回NULL;//并打印一个错误
如果(!BuildValueCheck(s,v1))
返回NULL;//并打印一个错误
返回Py_BuildValue(格式为v1);
}
模板
PyObject*构建值(字符*格式,t1 v1,t2 v2)
{
//跳过此处所有“()[]”等
char*s=strchr(格式为“ifsz…”);
如果(!s)
返回NULL;
如果(!BuildValueCheck(s,v1))
返回NULL;
s=strchr(s+1,“ifsz…”);
如果(!s)
返回NULL;
如果(!BuildValueCheck,v2))
返回NULL;
返回Py_BuildValue(格式为v1、v2);
}
//等等,对于3,4,5个参数-我怀疑你的程序使用更多
//然后在整个代码中用BuildValue替换所有Py#u BuildValue,或者做一个#define

请具体一点。答案取决于你要包装的函数的确切签名,更重要的是取决于你需要如何使用包装器。@Jan,我添加了C代码,我试图使C++可变函数不会造成任何麻烦,不管告诉与否。它们的类型安全性甚至不如C的其他部分,但是已经造成了损害。根据特定的接口,通过巧妙地应用模板或仅将自己限制在特定的情况下,可以撤销它,也可能无法撤销它。@Jan不知道你是否用变量调试过错误,这很痛苦…:(是否有一个C++模拟到PyvVabuIdDalk),即使你改变了你的签名还是改写为IoSo流传风格