2010-06-22 51 views
7

我有一些代码将Python与C++接口工作正常,但每次我看它时,都认为必须有更好的方法来实现它。在C++端有一个'变种'类型,可以处理固定范围的基本类型 - int,real,string,变体向量等。我有一些使用Python API从等效Python类型转换的代码。它看起来像这样:Python C API:打开PyObject类型

variant makeVariant(PyObject* value) 
{ 
    if (PyString_Check(value)) { 
    return PyString_AsString(value); 
    } 
    else if (value == Py_None) { 
    return variant(); 
    } 
    else if (PyBool_Check(value)) { 
    return value == Py_True; 
    } 
    else if (PyInt_Check(value)) { 
    return PyInt_AsLong(value); 
    } 
    else if (PyFloat_Check(value)) { 
    return PyFloat_AsDouble(value); 
    } 
    // ... etc 

问题是链式if-else ifs。它似乎在呼唤一个switch语句,或者一个由类型标识符键入的创建函数的表或映射。换句话说,我希望能够写类似:

return createFunMap[typeID(value)](value); 

基于API文档,这不是明显的脱脂最好的办法就是直接得到“TYPEID”在这里。我知道我可以做这样的事情:

PyTypeObject* type = value->ob_type; 

这显然让我很快就到了类型信息,但什么是使用涉及到一组有限的类型,我感兴趣的是干净的方式?

回答

3

从某种意义上说,我认为你已经回答了你自己的问题。

某处,您将不得不根据数据选择功能。在C中这样做的方法是使用函数指针。

创建一个object_type-> function mappers ...的映射,其中每个函数都有一个明确定义的接口。

variant PyBoolToVariant(PyObject *value) { 
    return value == Py_True; 
} 

Map<PyTypeObject*,variant* (PyObject*)> function_map; 

function_map.add(PyBool, PyBoolToVariant); 

现在你的makeVariant可以看起来像这样。

variant makeVariant(PyObject *value) { 
    return (*function_map.get(value->ob_type))(value); 
} 

困难的部分将获得Map对象的语法权限。另外,我假设有一个可以使用的Map对象,它带有类型参数(<PyTypeObject*, variant*(PyObject*))。

我可能还没有完全得到正确的第二种类型的地图的语法。它应该是一个指向一个函数的指针,它接受一个指针并返回一个指向变体的指针。

我希望这是有帮助的。

+0

谢谢。 function_map.add(PyBool,...你的答案的一部分足以让我在API文档的正确位置找到它,我认为这需要PyBool_Type而不是PyBool。我的问题的实质是真的什么是PyTypeObject的*值*,我需要使用它作为我的映射关键字,这会回答它。 – Bob 2010-06-22 13:57:18