Python C API: Включите тип PyObject

У меня есть некоторый код к интерфейсу Python к C++, который хорошо работает, но каждый раз я смотрю на него, я думаю, что должен быть лучший способ сделать это. На стороне C++ существует 'различный' тип, который может иметь дело с фиксированным диапазоном основных типов - интервал, реальный, строка, вектор вариантов, и т.д. У меня есть некоторый код с помощью API Python для преобразования из эквивалентных типов 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;

Это, по-видимому, получает меня быстро к информации о типе, но что самый чистый путь состоит в том, чтобы использовать это для касаний ограниченного набора типов, которыми я интересуюсь?

7
задан Wichert Akkerman 13 August 2012 в 08:09
поделиться

1 ответ

В некотором смысле, я думаю, вы ответили на свой вопрос.

Где-то вам придется выбирать функции на основе данных. В C это можно сделать с помощью указателей на функции.

Создайте карту сопоставителей object_type-> function ... где каждая функция имеет четко определенный интерфейс.

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, который принимает параметры типа ( ).

Я, вероятно, не совсем понял синтаксис второго типа карты. Это должен быть указатель на функцию, которая принимает один указатель и возвращает указатель на вариант.

Надеюсь, это полезно.

3
ответ дан 7 December 2019 в 16:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: