2010-06-22 8 views
7

Ho un codice per interfacciare Python a C++, che funziona bene ma ogni volta che lo guardo penso che ci sia un modo migliore per farlo. Sul lato C++ c'è un tipo 'variant' che può trattare con una gamma fissa di tipi di base - int, reale, stringa, vettore di varianti, ecc. Ho del codice usando l'API Python per convertire dai tipi Python equivalenti. Assomiglia a questo:API C Python: attivare il tipo 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 

Il problema è se if else altrimenti incatenato. Sembra che stia chiamando per un'istruzione switch, o una tabella o mappa di funzioni di creazione che è codificata da un identificatore di tipo. In altre parole, voglio essere in grado di scrivere qualcosa di simile:

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

Sulla base di un magro della documentazione API non era evidente ciò che il modo migliore è quello di ottenere il 'TypeId' qui direttamente. Vedo che posso fare qualcosa di simile:

PyTypeObject* type = value->ob_type; 

Questo mi viene apparentemente rapidamente le informazioni sul tipo ma qual è il modo più pulito per l'uso che per riguardare l'insieme limitato di tipi Sono interessato a?

risposta

3

In un certo senso, penso che tu abbia risposto alla tua stessa domanda.

Da qualche parte, dovrai selezionare la funzionalità in base ai dati. Il modo per farlo in C è usare i puntatori di funzione.

Creare una mappa di object_type-> function mappers ... dove ogni funzione ha un'interfaccia chiaramente definita.

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

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

function_map.add(PyBool, PyBoolToVariant); 

Ora il tuo makeVariant può assomigliare a questo.

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

La parte difficile sta per ottenere la sintassi giusta per l'oggetto Mappa. Inoltre, suppongo che ci sia un oggetto Mappa che puoi usare che prende i parametri del tipo (<PyTypeObject*, variant*(PyObject*)).

Probabilmente non ho ancora ottenuto la sintassi corretta per il secondo tipo di mappa. Dovrebbe essere un puntatore a una funzione che accetta un puntatore e restituisce un puntatore a una variante.

Spero che questo sia utile.

+0

Grazie. Il file function_map.add (PyBool, ... parte della tua risposta era abbastanza per me da cercare nel posto giusto nel documento API. Penso che questo dovrebbe essere PyBool_Type piuttosto che PyBool. L'essenza della mia domanda era davvero quali sono i * valori * di PyTypeObject che dovevo usare come chiave della mia mappa e questo lo risponde. – Bob