Pergunta

Estou tendo alguns problemas sérios para obter um mecanismo C ++ baseado em Python 2 para trabalhar no Python3. Eu sei que toda a pilha de IO mudou, mas tudo o que parece tentar acaba no fracasso. Abaixo está o pré-código (Python2) e o código postal (Python3). Espero que alguém possa me ajudar a descobrir o que estou fazendo de errado. Também estou usando boost::python Para controlar as referências.

O programa deve carregar um objeto Python na memória por meio de um mapa e, ao usar a função de execução, encontra o arquivo carregado na memória e o executa. Baseei meu código em um exemplo do Delta3D Python Manager, onde eles carregam em um arquivo e o executam imediatamente. Eu não vi nada equivalente no Python3.


O código Python2 começa aqui:

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

Em seguida, carrego o arquivo do mapa std :: e tento executá -lo:

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

O código Python3 começa aqui: é isso que eu tenho até agora com base em algumas sugestões aqui ... Então perguntaCarregar:

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

Corre:

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

Por fim, o estado geral do programa neste momento é o arquivo é carregado como TextIOWrapper E em execução: Seção o FD que é retornado é sempre 3 e, por algum motivo _fdopen nunca pode abrir o FILE O que significa que eu não posso fazer algo como PyRun_SimpleFile. O erro em si é uma depuração ASSERTION sobre _fdopen. Existe uma maneira melhor de fazer tudo isso, eu realmente aprecio qualquer ajuda.

Se você quiser ver o programa completo da versão python2, está ligado Github

Foi útil?

Solução

Portanto, essa pergunta foi muito difícil de entender e sinto muito, mas descobri que meu código antigo não estava funcionando como eu esperava. Aqui está o que eu queria que o código fizesse. Carregue o arquivo python na memória, armazene -o em um mapa e, em uma data posterior, execute esse código na memória. Consegui isso um pouco diferente do que eu esperava, mas faz muito sentido agora.

  1. Abra o arquivo usando ifstream, consulte o código abaixo
  2. Converta o char em um impulso :: python :: str
  3. Execute o impulso :: python :: str com boost :: python :: executão
  4. Lucro ???

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

Etapa 2) bp :: str file_str (string (& input [0])); LoadEd_Files_.insert (std :: make_pair (std :: string (fullpath (nome do arquivo)), file_str)); Etapa 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);

O código completo está localizado em Github:

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top