سؤال

أواجه بعض المتاعب الخطيرة في الحصول على محرك C ++ المستند إلى Python 2 للعمل في Python3. أعلم أن مكدس IO بالكامل قد تغير ، لكن كل ما يبدو أنني أحاوله ينتهي في الفشل. فيما يلي رمز ما قبل الرمز (Python2) والرمز النشر (Python3). آمل أن يتمكن شخص ما من مساعدتي في معرفة ما أفعله خطأ. أنا أيضًا أستخدم boost::python للسيطرة على المراجع.

من المفترض أن يقوم البرنامج بتحميل كائن بيثون في الذاكرة عبر خريطة ثم عند استخدام وظيفة التشغيل ، ثم يجد الملف المحمّل في الذاكرة ويقوم بتشغيله. لقد استندت إلى الكود الخاص بي على مثال من Delta3d Python Manager ، حيث يتم تحميلهم في ملف وتشغيله على الفور. لم أر أي شيء مكافئ في Python3.


يبدأ رمز Python2 هنا:

    // 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();
    }

بعد ذلك ، أقوم بتحميل الملف من الخريطة STD :: ومحاولة تنفيذها:

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

يبدأ رمز Python3 هنا: هذا ما قمت به حتى الآن من بعض الاقتراحات هنا ... لذلك سؤالحمل:

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

يركض:

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

أخيرًا ، يتم تحميل الحالة العامة للبرنامج في هذه المرحلة TextIOWrapper وفي المدى: القسم FD الذي يتم إرجاعه هو دائمًا 3 ولسبب ما _fdopen لا يمكن أن تفتح FILE مما يعني أنه لا يمكنني فعل شيء مثل PyRun_SimpleFile. الخطأ نفسه هو تصحيح ASSERTION تشغيل _fdopen. هل هناك طريقة أفضل للقيام بكل هذا ، وأنا أقدر حقًا أي مساعدة.

إذا كنت ترغب في رؤية البرنامج الكامل لإصدار Python2 ، فهو قيد التشغيل جيثب

هل كانت مفيدة؟

المحلول

لذلك كان من الصعب فهم هذا السؤال وأنا آسف ، لكنني اكتشفت أن الكود القديم لم يكن يعمل تمامًا كما كنت أتوقع. إليك ما أردت أن يفعله الرمز. قم بتحميل ملف Python في الذاكرة ، وقم بتخزينه في خريطة ثم في وقت لاحق قم بتنفيذ هذا الرمز في الذاكرة. لقد أنجزت هذا بشكل مختلف قليلاً عما كنت أتوقع ، لكن من المنطقي الآن.

  1. افتح الملف باستخدام ifstream ، راجع الرمز أدناه
  2. تحويل Char إلى Boost :: Python :: Str
  3. Execute the Boost :: Python :: Str with Boost :: Python :: Exec
  4. ربح ؟؟؟

الخطوة 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');

الخطوة 2) bp :: str file_str (string (& input [0])) ؛ loaded_files_.insert (std :: make_pair (std :: string (fullpath (filename)) ، file_str)) ؛ الخطوه 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);

يقع الكود الكامل على جيثب:

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top