SWIG:Lua - 传递一个c ++实例作为lua函数参数 [英] SWIG:Lua - Passing a c++ instance as a lua function parameter

查看:378
本文介绍了SWIG:Lua - 传递一个c ++实例作为lua函数参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm exporting some c++ classes to Lua with SWIG. I have declared boost::filesystem::path in the SWIG interface file like this:

namespace boost
{
    namespace filesystem
    {
        class path {};
    }
}



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

Now I want to call a function declared in a lua script which should take a boost::filesystem::path& as parameter to pass it to another object. I only need to be able to pass the path to the object. I don't need to use any functionality from the path object.

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



我将从c ++调用Lua函数。

I am going to call the Lua function from c++ using it's index.

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函数的参数?

THE QUESTION: How to push a boost::filesystem::path as a parameter to the Lua function?

推荐答案

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

This is actually fairly complicated. The expected use of SWIG is to create modules for Lua. The Lua script should be the one deciding what gets called and what doesn't. It isn't really meant for embedded use, where you use SWIG to expose some C++ objects and then call Lua code directly from your application.

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

That's not to say that it's impossible, just complicated.

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

All SWIG-based C++ objects are passed through Lua as pointers. Thus ownership is a question; you can't just shove a pointer to a stack object into Lua.

最安全的方法是将一个新的对象传递给Lua。这样,Lua拥有指针。 SWIG将知道Lua拥有指针,并且将附加一个适当的垃圾收集机制来清理它。所以一切都应该很好,内存聪明。

The safest way to do this is to pass a new copy of the object to Lua. That way, Lua owns the pointer. SWIG will know that Lua owns the pointer, and will attach a proper garbage collection mechanism to it to clean it up. So everything should be fine, memory wise.

但这样做需要正确的拳击(为了更好的术语)对象的SWIG想要的方式。这需要使用某些SWIG宏。

But doing this requires properly "boxing" (for want of a better term) that object the way that SWIG wants it done. This requires using certain SWIG macros.

由于您已将路径类型绑定到SWIG,像这样将其粘贴到Lua堆栈:

Given how you have bound the path type to SWIG, you would do something like this to stick it onto a Lua stack:

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所有权的指针; Lua的垃圾收集器将删除它感谢SWIG的metatables。此外 SWIG_NewPointerObj 将对象推送到 lua_State 堆栈。

SWIG_TypeQuery fetches the type of any object that has been bound by SWIG to Lua. This type info object is needed for SWIG_NewPointerObj, which takes a pointer to that type. Both of these are macros. SWIG_NewPointerObj gives Lua ownership of the pointer; Lua's garbage collector will delete it thanks to SWIG's metatables. Also SWIG_NewPointerObj pushes the object onto the lua_State stack.

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

Once it's on the stack, you can pretty much do whatever you want with it. Return it from a function to Lua, pass it to a Lua function as an argument, stick it in a global variable, etc. It's a Lua value.

你输入这个代码到你的项目,赔率是好的,当编译器看到 swig_type_info 时,你会得到一个编译错误。

Now, if you type this code into your project, odds are good that you'll get a compile error when the compiler sees swig_type_info. This type is defined internally within the source file generated by SWIG's command-line.

您有两个选项:


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

  1. Put this source code into the .swig file itself. Yes, really. You can define regular C++ functions there, within verbatum sections (the %{ %} delimited blocks). These functions will be copied directly into SWIG's generated code. You can access them by putting prototypes in headers. This is the simplest and easiest way to work. This is often used for creating special interfaces, where a pre-existing C++ function isn't appropriate for a Lua API (or simply doesn't exist).

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

You can generate an appropriate header that contains these definitions with the -external-runtime argument. This has to be a different SWIG execution step from the step that generates the .cpp file. See, it doesn't actually process the SWIG file or anything. All it needs is the target language (-lua) and whether you're using C++ (-c++).So just have a command that does swig -c++ -lua -external-runtime someheader.h, and that's all you need to get the types and macros.

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

Include that header in whatever source you want to attach SWIG-bound objects to Lua in.

这篇关于SWIG:Lua - 传递一个c ++实例作为lua函数参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆