2010-06-22 17 views
7

Tengo un código para la interfaz de Python a C++ que funciona bien, pero cada vez que lo veo, creo que debe haber una mejor manera de hacerlo. En el lado de C++ hay un tipo de "variante" que puede tratar con un rango fijo de tipos básicos: int, real, cadena, vector de variantes, etc. Tengo un código que usa la API de Python para convertir de los tipos de Python equivalentes. Se ve más o menos así:Python C API: encienda el tipo de 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 

El problema es el if-else encadenado. Parece estar llamando a una declaración de cambio, o una tabla o mapa de funciones de creación que está codificado por un identificador de tipo. En otras palabras, quiero ser capaz de escribir algo como:

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

Basado en una delgada de los documentos de la API no era obvio cuál es la mejor forma de hacerlo es conseguir el 'TypeId' aquí directamente. Veo que puedo hacer algo como esto:

PyTypeObject* type = value->ob_type; 

Al parecer, esto me lleva rápidamente a la información de tipo pero ¿cuál es la manera más limpia de usar que relacionarse con el conjunto limitado de tipos Estoy interesado?

Respuesta

3

En cierto modo, creo que ha respondido a su propia pregunta.

En algún lugar, tendrá que seleccionar la funcionalidad basada en los datos. La forma de hacer esto en C es usar punteros de función.

Crea un mapa de mapeadores de funciones object_type ... donde cada función tiene una interfaz claramente definida.

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

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

function_map.add(PyBool, PyBoolToVariant); 

Ahora su makeVariant puede verse así.

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

La parte difícil va a tener la sintaxis correcta para el objeto Map. Además, asumo que hay un objeto Map que puede usar que toma los parámetros de tipo (<PyTypeObject*, variant*(PyObject*)).

Probablemente no he conseguido la sintaxis correcta para el segundo tipo del Mapa. Debería ser un puntero a una función que toma un puntero y devuelve un puntero a una variante.

Espero que esto sea útil.

+0

Gracias. El function_map.add (PyBool, ... parte de tu respuesta fue suficiente como para que busque en el lugar correcto en el documento de la API. Creo que debe ser PyBool_Type en lugar de PyBool. La esencia de mi pregunta fue realmente cuáles son los * valores * de PyTypeObject que necesitaba usar como mi clave de mapa y esto lo responde. – Bob

Cuestiones relacionadas