【问题标题】:Implementing scripts in c++ app在 C++ 应用程序中实现脚本
【发布时间】:2010-09-08 23:48:26
【问题描述】:

我想将我的应用程序的各个部分移动到简单的脚本中,让不熟悉 c++ 的人能够编辑和实现各种功能。

因为它是一个实时应用程序,所以我需要对这些脚本进行某种多任务处理。理想情况下,我希望它让 c++ 应用程序调用一个脚本函数,然后继续运行(在 c++ 线程下),直到一个暂停点(Wait(x)),或者它返回。在等待的情况下,需要保存状态,以便在持续时间到期后下次应用循环时重新启动脚本。

脚本还需要能够调用 c++ 类方法,最好使用 c++ 类,而不是围绕 c++ 类的普通包装函数。

我不想花费大量时间来实现这一点,因此使用现有的脚本语言比编写自己的脚本语言更可取。听说可以将 Python 和 Lua 集成到一个 c++ 应用程序中,但我不知道如何做到这一点。

  • 脚本必须能够调用 c++ 函数
  • 脚本必须能够在调用某些函数时“暂停”(例如等待),并由 c++ 线程重新启动
  • 需要快速 - 这是一个实时应用程序,可能有很多脚本正在运行。

如果可以保存和重新启动脚本(可能通过与原始线程不同的线程),我可能可以相当轻松地滚动多任务代码。

【问题讨论】:

    标签: c++ scripting


    【解决方案1】:

    您可以使用 Lua 或 Python。 Lua 比 python 更“轻量级”。它的内存占用比 python 小,并且根据我们的经验更容易集成(人们在这一点上的里程可能会有所不同)。它可以支持一堆脚本同时运行。 Lua 至少支持以您希望的方式停止/启动线程。

    Boost.python 很好,但在我(有限的)经验中,我们很难为不同的环境进行编译,而且相当重量级。它有(在我看来)需要 Boost 的缺点。对某些人来说,这可能不是问题,但如果您不需要 Boost(或不使用它),您将引入大量代码来让 Boost.python 正常工作。 YMMV。

    我们已将 Lua 内置到多个平台(win32、Xbox360 和 PS3)上的应用程序中。我相信它可以在 x64 上运行。使用 Luabind 的建议很好。我们最终在两者之间编写了自己的接口,虽然不太复杂,但拥有该胶水代码将为您节省大量时间,也许还会让您烦恼。

    尽管使用任何一种解决方案,调试都可能会很痛苦。我们目前没有很好的解决方案来调试嵌入到我们应用程序中的 Lua 脚本。由于我们没有在我们的应用程序中使用 python,我无法谈论那里可能有哪些工具可用,但几年前情况大致相同——调试不佳。使用脚本来扩展功能固然不错,但脚本中的错误可能会导致问题并且可能难以定位。

    如果您需要在那里进行更改,则 Lua 代码本身有点混乱。我们已经在 Lua 代码库本身中看到了难以追踪的错误。我怀疑 Boost::Python 可能有类似的问题。

    对于任何脚本语言,它不一定是“非程序员”扩展功能的解决方案。看起来好像是这样,但您最终可能会花费大量时间来调试脚本,甚至可能是 Lua。

    总而言之,我们对 Lua 非常满意,并在两场比赛中发布了它。我们目前没有放弃该语言的计划。总而言之,我们发现它比几年前可用的其他替代品更好。 Python(和 IronPython)是其他选择,但根据经验,它们似乎比 Lua 更笨重。不过,我很想听听那里的其他经历。

    【讨论】:

    • 您究竟是如何让 Lua 与您的游戏一起工作的?例如,每个脚本是否一直在它自己的线程中运行直到完成,每个脚本是否像一个函数一样处理(即在调用线程中运行直到它返回),还是像它自己的小程序一样(就像我上面描述的那样)?跨度>
    • Lua 脚本可以在“线程”中运行,并且不一定需要像函数一样内联处理。它会做你想做的事。
    • 好的。然后我会更详细地看一下它并编写一些测试来确切地确定我希望如何将它与我的代码库集成:)
    【解决方案2】:

    我强烈建议您查看Luabind。它将 Lua 集成到您的 C++ 代码中变得非常简单,反之亦然。也可以公开整个 C++ 类以在 Lua 中使用。

    【讨论】:

      【解决方案3】:

      最好的办法是嵌入 lua (www.lua.org) 或 python (www.python.org)。两者都用于游戏行业,并且都相对容易地访问 extern "C" 函数,而 lua 在这里具有优势(因为数据类型更容易在 lua 和 C 之间转换)。与 C++ 对象的接口对您来说需要更多的工作,但您可以在 Google 或 lua 或 python 论坛上查找如何执行此操作。

      希望对你有帮助!

      【讨论】:

      • 好的,它们看起来都不错,但是它们是否支持暂停/重新启动以及我希望它们使用线程的方式(例如,使用调用脚本的线程,直到它返回或暂停)
      • 我没有在线程环境中使用过这两种方法。您可能想在 lua 和 python 特定论坛上发布这个问题。
      • @FireLancer:这对于你在 08 年的任何用途来说可能晚了两年,但是为了回答你今天可能读到这篇文章的任何人的问题:Lua 使用协程来做你所描述的事情。您可以调用“yield()”暂停协程,并调用“resume()”从中断处继续。您可以将参数传递给从前一个 resume() 返回的 yield(),并将参数传递给 resume(),这些参数将传递给正在恢复的相关 yield()。
      【解决方案4】:

      你绝对可以用 Python 做你想做的事。 Here are the docs on embedding Python into an application. 我很确定 Lua 也可以,只是我对它不太熟悉。

      您正在描述协作式多任务处理,其中脚本需要定期调用 Break 或 Wait 函数。也许更好的解决方案是在自己的线程中运行脚本语言,然后使用互斥锁或无锁队列作为脚本语言和程序其余部分之间的接口。这样,一个不经常调用 Break() 的错误脚本就不会意外冻结您的程序。

      【讨论】:

        【解决方案5】:

        看看Boost.Python 库。看起来做你想做的事情应该相当简单。

        【讨论】:

          【解决方案6】:

          看看SWIG。我用它来与 Python 交互,但它支持许多其他语言。

          【讨论】:

            【解决方案7】:

            再投一票给 Lua。它很小,速度很快,不会消耗太多内存(对于游戏,最好的选择是在初始化时分配大缓冲区并在那里重新定向所有 Lua 内存分配)。我们使用 tolua 生成绑定,但还有其他选项,其中大多数比 boost.python 更小/更易于使用 (IMO)。

            【讨论】:

              【解决方案8】:

              至于调试 Lua(如果你走那条路),我一直在使用 DeCoda,而且还不错。它假装是一个 IDE,但排序失败,但您可以将调试过程附加到 Visual Studio,并在断点处向下调用堆栈。非常方便追踪该错误。

              【讨论】:

                【解决方案9】:

                您还可以使用 Ch 嵌入 C/C++ 脚本。我一直在将它用于我正在从事的游戏项目,并且效果很好。力量和适应性的完美结合。

                【讨论】:

                  猜你喜欢
                  • 2010-11-12
                  • 2023-02-11
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-11-26
                  • 1970-01-01
                  • 2011-08-26
                  • 1970-01-01
                  相关资源
                  最近更新 更多