【问题标题】:Efficiently calling a Python function高效调用 Python 函数
【发布时间】:2011-10-12 01:52:36
【问题描述】:

我正在将 Python 嵌入到我的游戏中。这些脚本将用于定义角色 AI、实体对游戏事件的反应等——这意味着游戏中的每种实体都将有一个脚本。

每个脚本都会有一个类似createEntity() 的函数或返回构造实体的函数。调用这些函数的高效(ish)方式是什么(记住,每个实体的脚本中都有一个)。

我最初的想法是像您在下面看到的那样做一些事情,但是,我不确定这样做的效率如何。例如,在我运行该字符串后,导入的 hero 模块会发生什么?它是否仍然加载在主模块中?如果是这种情况,那就有问题了,因为我要为我可能需要添加到游戏世界的所有实体导入大量脚本。

boost::python::handle<> result(
    PyRun_String("import hero\n"    "createEntity()\n",
        Py_file_input, main_namespace.ptr(), main_namespace.ptr())
);

// Then extract the entity from `result`...

你有什么建议?

【问题讨论】:

  • 如果没有更多细节,我建议您可能会倒退。如果您想在 Python 中定义行为,则使用 Python 编写应用程序,调用 C++ 以实现与机器相关的快速路径活动。以您建议的方式嵌入 Python 可以弥补两种语言的缺陷,反过来却可以发挥它们的优势。
  • @msw 到目前为止,我一直认为最终结果应该是一个可执行文件(用 C++ 编写),它可以在需要时调用 Python 中定义的函数。我的图片有问题吗?
  • 无论哪种方式都可以——有调用 C 的 Python 游戏和嵌入 Python 的程序。
  • 要调用模块中的函数,您必须导入模块。要导入模块,您必须运行它(由于 Python 的动态性,也因为这是所有 Python 实现的方式,而您不想构建自己的半途而废的不兼容实现)。没有办法导入模块。你在期待什么?
  • 老实说,如果您正在为游戏制作嵌入式脚本语言,那么 JavaScript 或 Lua 可能是比 Python 更好的选择。它们是专门为嵌入而设计的,而 Python 往往希望从解释器和加载模块中运行。它们都使创建沙盒环境变得容易。它们更适合您尝试处理的问题。

标签: c++ python scripting boost embed


【解决方案1】:

您的问题没有具体说明空间效率(即内存)、时间效率还是劳动效率对您来说最重要。仅仅因为您正在考虑混合 C++/Python 应用程序,我认为劳动效率是一个重要因素。因为您正在开发一款游戏,我假设其中的某些部分需要极其严格的执行速度。

也许这种方法会取得平衡。使所有用户交互(输入和输出,包括任何网络)基于 C++ 以最小化延迟。你可以把它放在它自己的线程或进程中。给定模型中的高级事件,例如角色移动,此代码会非常快速地更新屏幕和网络。给定用户事件或来自网络的事件,它会向模型发送消息。

为了方便起见,可以与视图/控件异步的游戏模型在 Python 中,因此您可以利用函数式编程等。您可以在两者之间使用共享内存或类似的 IPC 机制,并且如果实际嵌入解释器不方便,请单独启动它们。

虽然某些 AI 应用程序是 CPU 密集型应用程序,因此可能很想为它们返回 C 或 C++,但我建议将其作为最后一步,以响应解释代码中明显的响应问题,如果您做吧。您甚至可能希望在图形方面也遵循这一思路,因为现在大多数图形处理都委托给视频硬件,如果您有办法从 Python 代码进行所需的库调用。

虽然我不是游戏开发人员,但我曾见过很少的情况,在这种情况下,单个等效 C 和 Python 操作之间的(现在)微秒差异对用户来说是可察觉的。可察觉的性能问题几乎总是由其他因素造成,例如磁盘 I/O、网络延迟或低效的算法实现。

【讨论】:

  • 根据提问者的其他帖子,似乎他可能首先尝试生成已编译的二进制文件。当有人假设二进制发行版更难破解时,我已经看到过这种问题。此类问题所假定的动机总是远远低于游戏黑客所表现出的动机。
  • @msw 你想得太远了(并且做出了太多假设)。我只想让可执行文件读取 Python 脚本;安全是我最关心的问题——如果他们想修改我的游戏,就这样吧。
【解决方案2】:

Ousterhout on the role of scripting languages 是老歌,但很好。对于您说要编写游戏玩法的游戏,模型(Python)已经按照您的描述组织了流程。如果 PyGame 或类似库不能胜任呈现视图的任务,请查找或构建一个 Python 模块。

换句话说,当我建议您向后集成时,听起来您是在要求视图重复调用模型以更新自身。我想不出一种方法可以将隐喻的马车放在马前,既能提高效率,又能提高开发的便利性。

【讨论】:

  • 这不完全取决于您想要的最终结果吗?我不想用 Python 写游戏;我想用 C++ 编写一个可以编写脚本的游戏。换句话说,“主要的东西”是 C++ 可执行文件,而不是 Python 脚本。
  • @Paul 这两者并不相互排斥...您始终可以让您的 C++ 可执行文件启动 Python 脚本,然后调用回 C++ 可执行文件。
  • “我不想用 Python 写游戏”。好吧,那就不要了。不过,您应该了解您的设计选择。 “因为这就是我想要的”当然是一个足够的答案,尽管不如“因为方法 X 比 Y 更好”那么令人满意。
  • 值得注意的是,Ousterhout 的文档仅涵盖命令行解释脚本语言。不涉及为嵌入而设计的脚本语言(Lua、JavaScript)。他所指的问题域(将多个应用程序捆绑在一起)不是提出问题的人正在处理的问题域。嵌入式脚本语言解决了与 Python 和 Perl 等 shell 脚本不同的问题。
  • 回复:尼可波拉斯:我不同意你的评价。 Ousterhout 也是 TCL 的创建者,TCL 一直被设计为嵌入式脚本语言。这种方法的真正优势在于它不规定集成工作的方式。考虑浏览器中的 javascript,它可以将浏览器提供的功能与外部 javascript 库以及浏览器插件的功能集成在一起。定义富互联网应用程序的不是浏览器,它只是主要用javascript编写的应用程序的解释器。
猜你喜欢
  • 2016-03-18
  • 2015-08-16
  • 2011-07-24
  • 2022-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-17
  • 1970-01-01
相关资源
最近更新 更多