【问题标题】:Creating a C++ DLL loadable by Lua创建可由 Lua 加载的 C++ DLL
【发布时间】:2011-04-04 07:10:03
【问题描述】:

我有一个小应用程序,它使用作为 dll 链接的 Lua(不是静态的)。我想使用 package.loadlib (libname, funcname) 通过 Lua 加载我自己的 c++ 编写的 dll。为此,我需要导出一个遵循 Lua 的lua_CFunction 协议的函数。显然出于这个原因,我必须将lua.h 合并到我的项目中并使用Lua 的函数来传递参数和结果。所以我的问题是:

  1. 我的 DLL 是否会使用已加载到小型应用进程中的 Lua dll?
  2. package.loadlib 是立即加载和卸载我的 DLL 还是加载后我的 DLL 会一直保留到 lua 脚本执行结束或应用程序终止?

【问题讨论】:

    标签: c++ c dll lua


    【解决方案1】:

    从您的具体问题开始:

    1. 可以,但前提是您的 DLL 隐式链接到它。请注意这一点,因为如果您不小心将 Lua VM 的两个副本链接到您的应用程序中,这可能会造成很大的混乱。就此而言,类似的问题也适用于 C 运行时。我会在Dependency Walker 下加载整个应用程序,以验证它只引用了一个 Lua DLL 实例和一个单一的 C 运行时。

    2. 我的理解是package.loadlib()只负责加载和链接到命名库中的命名函数。只要返回的函数对象(代表你命名的lua_CFunction)是活动的,那么这个DLL 肯定被加载了。如果您丢失了对该函数的最后一个引用,则该库可用于垃圾回收,如果被回收,它将被卸载。 Lua-L 邮件列表上有关于如何保证特定 DLL 被卸载的讨论,如果这是你关心的。否则,如果您只是假设 DLL 已加载,只要您可以访问其中存储的函数,就可以了。

    让我补充一点,基于此构建的模块系统是使用 C 或 C++ 代码扩展 Lua 的更好方法。 Chapter 26 of Programming in Lua 更详细地描述了这一点,链接是第一版在线副本中的该章节(描述 Lua 5.0)。请注意,模块系统在 Lua 5.1 和 Lua 5.2 中确实发生了一些变化。获取 PiL 的第二版或第三版(许多书商提供纸质版和电子版)可能会有所帮助。

    这里有一个执行摘要:要在 C 中创建一个名为 foo 的模块,您需要创建 foo.dll,它至少导出一个原型为 int luaopen_foo(lua_State *L) 的函数。该函数应该加载您的模块(通常通过在 Lua 5.1 中使用 luaL_register() 或在 Lua 5.2 中使用 luaL_newlib()luaL_setfuncs() 来注册一个充满 C 函数的表)并返回该表。在 Lua 方面,您将 DLL 放在package.cpath 中描述的路径上的某个位置,然后可以通过类似local foo = require "foo" 的代码加载它。各种 Lua 5.x 版本之间还有其他细微差别,但创建可以为任何版本编译的 C 代码相对简单。

    这样做的好处是,模块可以从路径加载,可以用 C 或 Lua 或两者混合编写,并且可以与其他模块很好地配合使用。您还可以通过一次 require 调用加载尽可能多或尽可能少的 C 函数。

    【讨论】:

    • 非常感谢您的出色回答。这对我帮助很大!除了 Lua 功能之外,我希望我的 DLL 连接到应用程序的 WndProc 并添加我的自定义工具栏,因此我不希望我的 DLL 在我不知道的情况下被卸载。
    • 你可以通过持有你自己对它的额外引用来获得对其生命周期的一些明确控制,只有在你准备好时才释放它。您可以使用luaL_ref()LUA_REGISTRYINDEX 处的表来引用可以在C 端保存(以整数形式)并通过luaL_unref() 释放的任何对象。
    • 对于刚刚发现这个问题的任何人,从 Lua 5.2 开始,luaL_register 已弃用; luaL_newlib 应该被使用,因为动态加载的模块不应该在全局环境中注册任何东西。
    • @bcrist 我已更新答案以包含指向 5.2 参考手册的链接,以提示最佳实践随着时间的推移而发生变化。
    【解决方案2】:

    您可以动态链接到与您的应用程序中相同的 Lua dll。

    至于 package.loadlib,我不知道它是如何工作的。阅读源代码?

    【讨论】:

      猜你喜欢
      • 2012-11-03
      • 2013-12-15
      • 1970-01-01
      • 2013-03-29
      • 1970-01-01
      • 2020-07-18
      • 1970-01-01
      • 2017-01-16
      • 1970-01-01
      相关资源
      最近更新 更多