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

时间:2012-02-26 17:55:53

标签: c++ lua swig

我正在用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 个答案:

答案 0 :(得分:6)

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

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

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

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

但这样做需要正确的#34;拳击&#34; (因为缺少更好的术语)反对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, outputType, 1);

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

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

现在,如果您在项目中键入此代码,那么当编译器看到swig_type_info时,您可能会遇到编译错误。此类型在SWIG的命令行生成的源文件中内部定义。

您有两种选择:

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

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

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