2011-01-05 7 views
0

Ich habe einige ernsthafte Probleme, eine Python 2-basierte C++ - Engine in Python3 arbeiten zu lassen. Ich weiß, dass sich der gesamte IO-Stack geändert hat, aber alles, was ich zu versuchen versuche, scheitert. Unten finden Sie den Pre-Code (Python2) und den Post-Code (Python3). Ich hoffe, dass jemand mir helfen kann herauszufinden, was ich falsch mache. Ich verwende auch , um die Referenzen zu kontrollieren.Python 3 C-API IO und Dateiausführung

Das Programm soll ein Python-Objekt über eine Map in den Speicher laden und dann mit der run-Funktion die Datei im Speicher finden und ausführen. Ich habe meinen Code von einem Beispiel aus dem delta3d Python Manager abgeleitet, wo er eine Datei lädt und sofort ausführt. Ich habe in Python3 nichts Vergleichbares 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(); 
    } 

Next ich die Datei aus dem std :: map laden und versuchen, sie auszuführen:

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

Python3 Code begins here : Dies ist, was ich bis jetzt einige Vorschläge hier basieren ... SO Question Load:

 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)); 

Run:

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 Zustand des Programms an diesem Punkt ist die Datei als TextIOWrapper und im Run geladen in wird: Abschnitt der fd die zurückgegeben wird, ist immer 3 und Aus irgendeinem Grund _fdopen kann nie öffnen FILE was bedeutet, dass ich etwas wie PyRun_SimpleFile nicht tun kann. Der Fehler selbst ist ein Debug ASSERTION auf _fdopen. Gibt es einen besseren Weg all dies zu tun, schätze ich jede Hilfe.

Wenn Sie das vollständige Programm der Python2 Version sehen wollen es auf Github ist

+0

Ich bin verwirrt an, was Sie zu tun versuchen. Welche der obigen Python 3 Beispiele sollen welche der obigen Python 2 Beispiele ersetzen? Sie sind alle so verschieden. Und was ist Ihre eigentliche Fehlermeldung? –

+0

Gut genug, ich habe ein paar Änderungen vorgenommen und im zweiten Absatz ein wenig mehr darüber erklärt, was ich zu erreichen versuche. –

+0

Ich habe vielleicht die Lösung gefunden, aber ich kann es nicht testen, bis ich nach Hause komme. Wenn ich es tue, werde ich es posten. –

Antwort

0

So war diese Frage ziemlich schwer zu verstehen, und es tut mir Leid, aber ich fand meinen alten Code aus war nicht ganz funktioniert wie Ich erwartete. Hier ist, was ich mit dem Code machen wollte. Laden Sie die Python-Datei in den Speicher, speichern Sie sie in einer Map und führen Sie diesen Code zu einem späteren Zeitpunkt im Speicher aus. Ich habe das etwas anders gemacht, als ich erwartet hatte, aber es macht jetzt sehr viel Sinn.

  1. Öffnen Sie die Datei ifstream finden Sie unter den nachfolgenden Code
  2. umrechnen char in eine boost :: Python :: str
  3. Führen Sie die boost :: python :: str mit boost :: Python :: exec
  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 (& Eingang [0])); loaded_files_.insert (std :: make_pair (std :: string (vollständiger Pfad (Dateiname)), Datei_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); 

Voll-Code auf github befindet: