Es scheint, dass die Python C-API nicht mit der const-Korrektheit von Zeichenarrays übereinstimmt. Zum Beispiel akzeptiert PyImport_ImportFrozenModule ein char*
, während PyImport_ImportModule akzeptiert eine const char*
.
Die Folge davon ist, dass ich in meiner C ++ - Anwendung, die ich mit einem eingebetteten Python-Interpreter schreibe, das String-Literal, das ich an einen Python-API-Aufruf übergebe, nur als char*
(im Gegensatz zu const char*
), und manchmal nicht. Zum Beispiel:
Wenn ich das const_cast<char*>
(oder (char*)
) im String-Literal nicht mache, erhalte ich eine Compiler-Warnung, dass String-Literale an char*
übergeben werden.
Hier sind meine Fragen:
const char*
benötigen (und / oder warum würde die Python-API nicht konsistent sein)? Mein Verständnis ist, dass, wenn die Funktion ein String-Literal annehmen kann, sie char*
nicht ändern kann, so würde der const
-Modifikator das nur verstärken. Ich glaube auch, dass die const
Unterscheidung nicht so wichtig für C ist (für die die API geschrieben wurde) als in C ++ (korrigiere mich, wenn ich falsch liege ... meine Stärke ist Python, nicht C / C ++). Ist das Fehlen der "Const-Korrektheit" der Python-API, weil es in C einfach nicht so wichtig ist? (Es gibt einen alten Thread auf der Python-Mailing-Liste von 2000, der das gleiche fragt Frage, aber es scheint nicht zu gehen irgendwo und es ist impliziert, der Grund könnte aufgrund einiger Compiler sein, die const
nicht unterstützen. Da viele Funktionen jetzt const char*
haben, scheint dies nicht mehr zu gelten) Da mein Verständnis von C ++ begrenzt ist, bin ich mir nicht sicher, ob ich String-Literale richtig umwandeln werde. So wie ich es sehe, kann ich entweder eine der folgenden (ich mache gerade die erste):
%Vor%Welches ist die beste Methode?
Aktualisierung:
Es sieht so aus, als ob der Python3-Zweig langsam versucht, das Problem der const-Korrektheit zu beheben. Die PyImport_ImportFrozenModule
-Funktion, die ich als Beispiel oben verwende, nimmt nun in Python 3.4 const char*
an, aber es gibt immer noch Funktionen, die nur ein char*
benötigen, wie zB PyLong_FromString .
Basierend auf einigen Mailinglisten-Konversationen von python-dev, sieht es so aus, als ob die ursprüngliche API einfach nicht mit konstanter Korrektheit erstellt wurde, wahrscheinlich nur weil Guido nicht darüber nachdachte. Da sie bis ins Jahr 2002 zurückdatierten, fragte jemand , ob es einen Wunsch gab, dies durch Hinzufügen von const zu lösen - Korrektheit, beschweren, dass es ein Schmerz ist, immer dies tun zu müssen:
%Vor%Guido Van Rossum (der Schöpfer von Python) geantwortet (Hervorhebung von mir):
Ich habe nie versucht, die const-Korrektheit vor durchzusetzen, aber ich habe gehört genug Horrorgeschichten darüber. Das Problem ist, dass es 3. bricht Party-Erweiterungen links und rechts, und das zu beheben ist nicht immer einfach. Im Allgemeinen wird jedes Mal, wenn Sie irgendwo eine Konstante hinzufügen, die Propagierung fortgesetzt zu einer anderen API, die dann auch eine const benötigt, die propagiert zu einer weiteren API, die eine const, ad infinitum benötigt.
Es gab ein bisschen mehr Diskussion, aber ohne die Unterstützung von Guido ist die Idee gestorben.
Schnell vor neun Jahren, und das Thema kam wieder auf. Diesmal fragte sich jemand, warum manche Funktionen korrekt waren, andere nicht. Einer der Python-Hauptentwickler antwortete darauf :
Wir haben im Laufe der Jahre viele Orte hinzugefügt. Ich denke der spezieller Fall wurde gerade verpasst (d. h. niemand kümmerte sich darum, const dort).
Wenn Const-Korrektheit möglich ist, ohne die Rückwärtskompatibilität zu unterbrechen, wurde sie an vielen Stellen in der C-API hinzugefügt (und im Fall von Python 3 an Stellen, an denen wäre) Abwärtskompatibilität mit Python 2), aber es gab nie eine echte globale Anstrengung, es überall zu reparieren . Also ist die Situation in Python 3 besser, aber die gesamte API ist wahrscheinlich auch jetzt nicht const korrekt.
Ich glaube nicht, dass die Python-Community eine bevorzugte Methode hat, Casting mit Aufrufen durchzuführen, die nicht const
-korrekt sind (es gibt keine Erwähnung im offiziellen C-API Styleguide ), wahrscheinlich weil es nicht viele Leute gibt, die mit der C-API aus C ++ - Code interagieren. Ich würde sagen, dass der bevorzugte Weg, dies aus einer reinen C ++ - Best-Practice-Perspektive zu tun, die erste Wahl wäre. (Ich bin auf keinen Fall ein C ++ - Experte, also nehmen Sie das mit einem Körnchen Salz).
Gibt es einen Vorteil / Grund dafür, dass einige der Funktionen nicht
const char*
übernehmen?
Nein. Sieht nach einem Versehen im Design der Bibliothek aus oder, wie Sie sagen, aus Altlasten. Sie hätten es zumindest konsistent machen können!
Nach meinem Verständnis kann die Funktion
char*
nicht ändern, wenn die Funktion ein Zeichenfolgenliteral verwenden kann, damit der Modifikatorconst
dies nur verstärkt.
Genau. In ihrer Dokumentation sollte auch angegeben werden, dass das Funktionsargument (oder besser der Argumentpunkt des Arguments) während des Funktionsaufrufs nicht geändert werden darf; leider sagt es das derzeit nicht.
Ich glaube auch, dass die Unterscheidung
const
für C (für die die API geschrieben wurde) nicht so wichtig ist wie für C ++.
Nun, nicht wirklich, zumindest soweit ich weiß.
So wie ich es sehe, kann ich entweder eine der folgenden (ich mache gerade die erste)
(gut)
Welches ist die beste Methode?
Nun, der const_cast
wird zumindest dafür sorgen, dass Sie nur die const
-ness ändern, also wenn Sie wählen müssten, würde ich damit gehen. Aber wirklich, ich würde mich nicht zu sehr darum kümmern.
Tags und Links python c++ python-c-api