Python 3 C-API IO и выполнение файлов - PullRequest
0 голосов
/ 05 января 2011

У меня серьезные проблемы с получением движка C ++ на основе Python 2 для работы в Python3. Я знаю, что весь стек ввода-вывода изменился, но все, что я пытаюсь сделать, просто заканчивается неудачей. Ниже приведен пре-код (Python2) и почтовый индекс (Python3). Я надеюсь, что кто-то может помочь мне понять, что я делаю неправильно. Я также использую boost::python для управления ссылками.

Предполагается, что программа загружает объект Python в память через карту, а затем, используя функцию запуска, находит файл, загруженный в память, и запускает его. Я основал свой код на примере из менеджера Python delta3d, где они загружаются в файл и запускают его немедленно. Я не видел ничего эквивалентного в 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 :: map и пытаюсь его выполнить:

    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, а в разделе Run: возвращаемое fd всегда равно 3 и по какой-то причине _fdopen никогда не может открыть FILE, что означает, что я не могу сделать что-то вроде PyRun_SimpleFile. Сама ошибка является отладкой ASSERTION на _fdopen. Есть ли лучший способ сделать все это, я действительно ценю любую помощь.

Если вы хотите увидеть полную программу версии Python2, она включена Github

1 Ответ

0 голосов
/ 06 января 2011

Так что этот вопрос было довольно сложно понять, и я извиняюсь, но я обнаружил, что мой старый код работает не совсем так, как я ожидал. Вот что я хотел, чтобы код делал. Загрузите файл python в память, сохраните его в карту, а затем выполните этот код в памяти. Я сделал это немного иначе, чем ожидал, но теперь это имеет большой смысл.

  1. Откройте файл, используя ifstream, см. Код ниже
  2. Преобразование символа в повышение :: python :: str
  3. Выполнить boost :: python :: str с 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 (строка (& input [0])); загруженный_файл_.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);

Полный код находится на github :

...