2010-06-22 5 views
7

Ich habe etwas Code, um Python mit C++ zu verbinden, was gut funktioniert, aber jedes Mal, wenn ich es mir anschaue, muss es einen besseren Weg geben, es zu tun. Auf der C++ - Seite gibt es einen "Variante" -Typ, der mit einem festen Bereich von Grundtypen umgehen kann - Int, Real, String, Vektor von Varianten, usw. Ich habe Code, der die Python-API verwendet, um von den entsprechenden Python-Typen zu konvertieren. Es sieht in etwa so aus:Python C API: Schalten Sie PyObject ein

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 

Das Problem ist das angekettete if-else ifs. Es scheint nach einer switch-Anweisung oder nach einer Tabelle oder einer Karte von Erstellungsfunktionen zu fragen, die durch einen Typidentifizierer getastet wird. Mit anderen Worten mag ich in der Lage sein, etwas zu schreiben wie:

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

Basierend auf einem Skim der API-Dokumentation es nicht offensichtlich, was der beste Weg war, ist die ‚typeID‘ direkt hier. Ich sehe ich etwas tun kann:

PyTypeObject* type = value->ob_type; 

Das bin ich anscheinend schnell auf die Typinformationen bekommt, aber was ist der sauberste Weg, das zu verwenden, um die begrenzte Anzahl von Arten in Ich bin zu beziehen interessiert?

Antwort

3

In gewisser Weise denke ich, Sie haben Ihre eigene Frage beantwortet.

Irgendwo müssen Sie die Funktionalität basierend auf Daten auswählen. Die Methode in C besteht darin, Funktionszeiger zu verwenden.

Erstellen Sie eine Karte von object_type-> function mappers ... wo jede Funktion eine klar definierte Schnittstelle hat.

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

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

function_map.add(PyBool, PyBoolToVariant); 

Jetzt kann Ihr makeVariant so aussehen.

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

Der schwierige Teil wird die Syntax für das Map-Objekt erhalten. Außerdem nehme ich an, dass es ein Map-Objekt gibt, das Sie verwenden können, das Typparameter (<PyTypeObject*, variant*(PyObject*)) nimmt.

Ich habe wahrscheinlich nicht richtig die Syntax für den zweiten Typ der Karte richtig. Es sollte ein Zeiger auf eine Funktion sein, die einen Zeiger nimmt und einen Zeiger auf eine Variante zurückgibt.

Ich hoffe, das ist hilfreich.

+0

Danke. Der Teil von function_map.add (PyBool, ...) war genug von einem Hinweis, dass ich an der richtigen Stelle im API-Dokument suchen sollte. Ich denke, das muss PyBool_Type sein, nicht PyBool. Das Wesentliche meiner Frage war wirklich Was sind die * Werte * von PyTypeObject, die ich als Kartenschlüssel verwenden musste, und dies beantwortet sie. – Bob