SWIG:Lua - 将 c++ 实例作为 lua 函数参数传递

Posted

技术标签:

【中文标题】SWIG:Lua - 将 c++ 实例作为 lua 函数参数传递【英文标题】:SWIG:Lua - Passing a c++ instance as a lua function parameter 【发布时间】:2012-02-26 17:55:53 【问题描述】:

我正在使用 SWIG 将一些 c++ 类导出到 Lua。我在 SWIG 接口文件中声明了 boost::filesystem::path,如下所示:

namespace boost

    namespace filesystem
    
        class path ;
    

现在我想调用一个在 lua 脚本中声明的函数,它应该将 boost::filesystem::path& 作为参数传递给另一个对象。我只需要能够将路径传递给对象。我不需要使用路径对象中的任何功能。

function on_path_selected(the_path)
    another_object:set_path(the_path)
end

我将使用它的索引从 c++ 调用 Lua 函数。

lua_rawgeti(L, LUA_REGISTRYINDEX, m_function_index);
lua_push[SOMETHING](L, path_object); // <-- HOW TO ?
lua_pcall(L,1,0,0)

问题:如何将 boost::filesystem::path 作为参数推送到 Lua 函数?

【问题讨论】:

【参考方案1】:

这实际上相当复杂。 SWIG 的预期用途是为 Lua 创建模块。 Lua 脚本应该是决定调用什么和不调用什么的脚本。它并不是真正用于嵌入式使用,您使用 SWIG 公开一些 C++ 对象,然后直接从您的应用程序调用 Lua 代码。

这并不是说不可能,只是很复杂。

所有基于 SWIG 的 C++ 对象都通过 Lua 作为指针传递。因此,所有权是一个问题;你不能只是将一个指向堆栈对象的指针推入 Lua。

最安全的方法是将对象的新副本传递给 Lua。这样,Lua 就拥有了指针。 SWIG 将知道 Lua 拥有该指针,并将为其附加适当的垃圾收集机制以对其进行清理。所以一切都应该没问题,记忆明智。

但是这样做需要正确地“装箱”(因为需要一个更好的术语)来反对 SWIG 希望它完成的方式。这需要使用某些 SWIG 宏。

鉴于您如何将 path 类型绑定到 SWIG,您可以执行以下操作将其粘贴到 Lua 堆栈上:

swig_type_info *pathType = SWIG_TypeQuery("boost::filesystem::path *");
boost::filesystem::path *pArg = new boost::filesystem::path(the_path);
SWIG_NewPointerObj(L, pArg, pathType, 1);

SWIG_TypeQuery 获取已被 SWIG 绑定到 Lua 的任何对象的类型。 SWIG_NewPointerObj 需要此类型信息对象,它接受指向该类型的指针。这两个都是宏。 SWIG_NewPointerObj 赋予 Lua 指针的所有权;由于 SWIG 的元表,Lua 的垃圾收集器将删除它。同时SWIG_NewPointerObj 将对象推入lua_State 堆栈。

一旦它在堆栈上,你几乎可以用它做任何你想做的事情。将其从函数返回到 Lua,将其作为参数传递给 Lua 函数,将其粘贴到全局变量中,等等。这是一个 Lua 值。

现在,如果您将这段代码输入到您的项目中,当编译器看到swig_type_info 时,您很有可能会收到编译错误。此类型在 SWIG 命令行生成的源文件中在内部中定义。

你有两个选择:

    将此源​​代码放入 .swig 文件本身。对真的。您可以在逐字部分(%% 分隔块)中定义常规 C++ 函数。这些函数将直接复制到 SWIG 生成的代码中。您可以通过将原型放在标题中来访问它们。这是最简单、最简单的工作方式。这通常用于创建特殊接口,其中预先存在的 C++ 函数不适用于 Lua API(或根本不存在)。

    您可以使用-external-runtime 参数生成包含这些定义的适当标头。这必须是与生成 .cpp 文件的步骤不同的 SWIG 执行步骤。看,它实际上并没有处理 SWIG 文件或任何东西。它所需要的只是目标语言 (-lua) 以及您是否使用 C++ (-c++)。所以只需一个执行 swig -c++ -lua -external-runtime someheader.h 的命令,这就是获取类型和宏所需的全部内容。

    在您想要将 SWIG 绑定对象附加到 Lua 的任何源中包含该标头。

【讨论】:

感谢您的出色回答。我目前正在挖掘生成的 SWIG cpp 源文件,我完全可以理解您所描述的内容的正确性。是的,似乎要找到一种优雅的方式来实现这项工作还有很长的路要走。非常感谢你!编辑:我会在看到按钮后立即将其标记为答案。

以上是关于SWIG:Lua - 将 c++ 实例作为 lua 函数参数传递的主要内容,如果未能解决你的问题,请参考以下文章

Swig + Lua:调用 m(int argv, char **argc)

SWIG Lua 和传递数组

从 C++ 将字节数组传递给 lua 脚本方法

C++与Lua交互实例 -- 矩阵的加减乘除(版本二)

使用 SWIG 包装 c++ 类以在 Lua 中使用它 - 需要简单的示例

如何获取从 C++ 发送到 Lua 函数的表的更新值?