1

我在让基于 Python 2 的 C++ 引擎在 Python3 中工作时遇到了一些严重的问题。我知道整个 IO 堆栈已经改变,但我似乎尝试的一切都以失败告终。下面是前代码(Python2)和后代码(Python3)。我希望有人可以帮助我找出我做错了什么。我也boost::python用来控制引用。

该程序应该通过映射将 Python 对象加载到内存中,然后在使用 run 函数时,它会找到加载到内存中的文件并运行它。我的代码基于来自 delta3d python 管理器的示例,它们加载到文件中并立即运行它。我在 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) );

最后,此时程序的一般状态是文件以 asTextIOWrapper和 Run: 部分加载,返回的 fd 始终为 3 并且由于某种原因_fdopen永远无法打开,FILE这意味着我无法执行类似PyRun_SimpleFile. 错误本身是ASSERTION_fdopen. 有没有更好的方法来做这一切我真的很感激任何帮助。

如果您想查看 Python2 版本的完整程序,请访问Github

4

1 回答 1

0

所以这个问题很难理解,很抱歉,但我发现我的旧代码并没有像我预期的那样工作。这就是我想要代码做的事情。将 python 文件加载到内存中,将其存储到地图中,然后稍后在内存中执行该代码。我完成这件事的方式与我预期的有所不同,但现在很有意义。

  1. 使用 ifstream 打开文件,看下面的代码
  2. 将 char 转换为 boost::python::str
  3. 使用 boost::python::exec 执行 boost::python::str
  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])); load_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);

完整代码位于github 上

于 2011-01-06T04:03:20.560 回答