Frage

Ich habe ernsthafte Probleme, eine auf Python 2 basierende C++-Engine in Python3 zum Laufen zu bringen.Ich weiß, dass sich der gesamte E/A-Stack geändert hat, aber alles, was ich versuche, schlägt einfach fehl.Unten finden Sie den Vorcode (Python2) und den Postcode (Python3).Ich hoffe, dass mir jemand helfen kann, herauszufinden, was ich falsch mache. Ich benutze es auch boost::python um die Referenzen zu kontrollieren.

Das Programm soll ein Python-Objekt über eine Karte in den Speicher laden und dann bei Verwendung der Ausführungsfunktion die im Speicher geladene Datei finden und ausführen.Ich habe meinen Code auf einem Beispiel des Python-Managers delta3d basiert, wo eine Datei geladen und sofort ausgeführt wird.Ich habe in Python3 nichts Äquivalentes gesehen.


Python2-Code beginnt hier:

    // what this does is first calls the Python C-API to load the file, then pass the returned
    // PyObject* into handle, which takes reference and sets it as a boost::python::object.
    // this takes care of all future referencing and dereferencing.
    try{
        bp::object file_object(bp::handle<>(PyFile_FromString(fullPath(filename), "r" )));
        loaded_files_.insert(std::make_pair(std::string(fullPath(filename)), file_object));
    }
    catch(...)
    {
        getExceptionFromPy();
    }

Als nächstes lade ich die Datei aus std::map und versuche, sie auszuführen:

    bp::object loaded_file = getLoadedFile(filename);
    try
    {
        PyRun_SimpleFile( PyFile_AsFile( loaded_file.ptr()), fullPath(filename) );
    }
    catch(...)
    {
        getExceptionFromPy();
    }

Python3-Code beginnt hier:Dies ist, was ich bisher basierend auf einigen Vorschlägen hier getan habe ... ALSO FrageBelastung:

        PyObject *ioMod, *opened_file, *fd_obj;

        ioMod = PyImport_ImportModule("io");
        opened_file = PyObject_CallMethod(ioMod, "open", "ss", fullPath(filename), "r");

        bp::handle<> h_open(opened_file);
        bp::object file_obj(h_open);
        loaded_files_.insert(std::make_pair(std::string(fullPath(filename)), file_obj));

Laufen:

    bp::object loaded_file = getLoadedFile(filename);
    int fd = PyObject_AsFileDescriptor(loaded_file.ptr());
    PyObject* fileObj = PyFile_FromFd(fd,fullPath(filename),"r",-1,"", "\n","", 0);

    FILE* f_open = _fdopen(fd,"r");

    PyRun_SimpleFile( f_open, fullPath(filename) );

Schließlich ist der allgemeine Status des Programms zu diesem Zeitpunkt, dass die Datei als geladen wird TextIOWrapper und im Lauf:Abschnitt ist der zurückgegebene fd immer 3 und das aus irgendeinem Grund _fdopen kann das nie öffnen FILE was bedeutet, dass ich so etwas nicht tun kann PyRun_SimpleFile.Der Fehler selbst ist ein Debug ASSERTION An _fdopen.Gibt es einen besseren Weg, das alles zu machen? Ich bin wirklich dankbar für jede Hilfe.

Wenn Sie das vollständige Programm der Python2-Version sehen möchten, klicken Sie hier Github

War es hilfreich?

Lösung

Diese Frage war also ziemlich schwer zu verstehen und es tut mir leid, aber ich habe festgestellt, dass mein alter Code nicht ganz so funktioniert hat, wie ich es erwartet hatte.Folgendes wollte ich mit dem Code tun.Laden Sie die Python-Datei in den Speicher, speichern Sie sie in einer Karte und führen Sie den Code zu einem späteren Zeitpunkt im Speicher aus.Ich habe das etwas anders hinbekommen, als ich erwartet hatte, aber jetzt macht es sehr viel Sinn.

  1. Öffnen Sie die Datei mit ifstream, siehe Code unten
  2. Wandeln Sie das Zeichen in einen boost::python::str um
  3. Führen Sie boost::python::str mit boost::python::exec aus
  4. Gewinn???

Schritt 1)

vector<char> input;
ifstream file(fullPath(filename), ios::in);
if (!file.is_open())
{
    // set our error message here
    setCantFindFileError();
    input.push_back('\0');
    return input;
}

file >> std::noskipws;
copy(istream_iterator<char>(file), istream_iterator<char>(), back_inserter(input));
input.push_back('\n');
input.push_back('\0');

Schritt 2) BP :: STR File_str (String (& input [0]));geladene_files_.insert(std::make_pair(std::string(fullPath(filename)), file_str));Schritt 3)

bp::str loaded_file = getLoadedFile(filename);
// Retrieve the main module
bp::object main = bp::import("__main__");
// Retrieve the main module's namespace
bp::object global(main.attr("__dict__"));
bp::exec(loaded_file, global, global);

Der vollständige Code befindet sich auf Github:

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top