Python C API: переключатель на тип PyObject
-
29-09-2019 - |
Вопрос
У меня есть какой-то код для интерфейса Python к C ++, который работает нормально, но каждый раз, когда я смотрю на него, я думаю, что должен быть лучший способ сделать это. На стороне C ++ есть тип «вариант», который может иметь дело с фиксированным диапазоном основных типов - int, Real, String, Vector Variants и т. Д. У меня есть какой-то код, используя 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
Проблема в привязке, если иначе IFS. Похоже, это вызывает для выключателя выключателя или таблицу или карту функций создания, которые включены идентификатор типа. Другими словами, я хочу иметь возможность написать что-то вроде:
return createFunMap[typeID(value)](value);
На основании обезжиренного документа API было не очевидно, какой лучший способ - получить здесь «Тип». Я вижу, что могу сделать что-то вроде этого:
PyTypeObject* type = value->ob_type;
Это, по-видимому, быстро приведет меня к информации о типе, но в чем самый чистый способ использовать это, чтобы связаться с ограниченным набором типов, которые меня интересуют?
Решение
В некотором смысле, я думаю, вы ответили на ваш вопрос.
Где-то вам придется выбрать функциональность на основе данных. Способ сделать это в C - использовать указатели функции.
Создайте карту Object_Type-> Function Mappers ... где каждая функция имеет четко определенный интерфейс.
variant PyBoolToVariant(PyObject *value) {
return value == Py_True;
}
Map<PyTypeObject*,variant* (PyObject*)> function_map;
function_map.add(PyBool, PyBoolToVariant);
Теперь ваш макиавариант может выглядеть так.
variant makeVariant(PyObject *value) {
return (*function_map.get(value->ob_type))(value);
}
Тяжелая часть собирается получить синтаксис прямо для объекта карты. Кроме того, я предполагаю, что существует объект карты, который вы можете использовать, который принимает параметры типа (<PyTypeObject*, variant*(PyObject*)
).
Я, вероятно, не совсем получил синтаксис правильной для второго типа карты. Это должно быть указателем на функцию, которая принимает один указатель и возвращает указатель на вариант.
Я надеюсь, что это полезно.