我有一些将 Python 与 C++ 接口的代码,工作得很好,但每次我看到它时,我都认为一定有更好的方法来实现。在 C++ 方面,有一个“变体”类型,可以处理固定范围的基本类型 - int、real、string、变体向量等。我有一些代码使用 Python API 从等效的 Python 类型进行转换。它看起来像这样:
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 if。它似乎正在调用 switch 语句,或者由类型标识符作为键的创建函数的表或映射。换句话说,我希望能够编写如下内容:
return createFunMap[typeID(value)](value);
根据 API 文档的浏览,直接获取“typeID”的最佳方法是什么并不明显。我发现我可以做这样的事情:
PyTypeObject* type = value->ob_type;
这显然可以让我快速获得类型信息,但是使用它来与我感兴趣的有限类型集相关的最干净的方法是什么?
I have some code to interface Python to C++ which works fine but every time I look at it I think there must be a better way to do it. On the C++ side there is a 'variant' type that can deal with a fixed range of basic types - int, real, string, vector of variants, etc. I have some code using the Python API to convert from the equivalent Python types. It looks something like this:
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
The problem is the chained if-else ifs. It seems to be calling out for a switch statement, or a table or map of creation functions which is keyed by a type identifier. In other words I want to be able to write something like:
return createFunMap[typeID(value)](value);
Based on a skim of the API docs it wasn't obvious what the best way is to get the 'typeID' here directly. I see I can do something like this:
PyTypeObject* type = value->ob_type;
This apparently gets me quickly to the type information but what is the cleanest way to use that to relate to the limited set of types I am interested in?
发布评论
评论(1)
在某种程度上,我认为你已经回答了你自己的问题。
在某些地方,您将必须根据数据选择功能。在 C 语言中实现这一点的方法是使用函数指针。
创建一个 object_type->function 映射器的映射...其中每个函数都有一个明确定义的接口。
现在你的 makeVariant 看起来像这样。
困难的部分是为 Map 对象获取正确的语法。另外,我假设您可以使用一个带有类型参数的 Map 对象 ()。
我可能还没有完全掌握第二种类型的地图的正确语法。它应该是一个指向函数的指针,该函数接受一个指针并返回一个指向变体的指针。
我希望这有帮助。
In a way, I think you've answered your own question.
Somewhere, you're going to have to select functionality based on data. The way to do this in C is to use function pointers.
Create a map of object_type->function mappers... where each function has a clearly-defined interface.
Now your makeVariant can look like this.
The hard part is going to be getting the syntax right for the Map object. Also, I'm assuming there is a Map object you can use that takes type parameters (
<PyTypeObject*, variant*(PyObject*)
).I probably have not quite gotten the syntax correct for the second type of the Map. It should be a pointer to a function which takes one pointer and returns a pointer to a variant.
I hope this is helpful.