在使用C++进行Lua扩展时,C++中丰富的参数接受、处理方式包括指针、引用、值传递、数组等,会使人疑问,这种函数在Lua中该怎样调用。
一、指针、引用,假设是这样一个demo,代码如下
//demo.h
void foo(int & val);
void foo1(int* val);
这两个函数的实现留在demo.cpp中,主要为打印一些内容以区分彼此。他的.i文件如下
//demo.i
%module example
%{
#include "demo.h"
%}
%include "cpointer.i"
%pointer_functions(int, intp);
%include "demo.h"
这里面的cpointer.i文件为swig提供的库文件,可以在swig的安装目录下的Lib中找到,执行这个例子
如果错误,可能是这个Lib路径SWIG_LIB没有加入到环境变量中。
%pointer_functions(type,name)将会为Lua提供几个接口函数,包括
1、type *new_name()
使用calloc创建type类型对象,并返回
2、type *copy_name(type value)
使用calloc创建type类型对象,并使用value进行初始化
3、type *delete_name(type *obj)
删除一个type类型对象
4、void name_assign(type *obj, type value)
对type对象obj赋值
5、type name_value(type *obj)
返回type对象obj的值
(注:这里说的对象是lua中的,在c++中可能是对象,也可能不是)
执行:swig -lua -c++ demo.i
生成的文件demo_wrap.cxx已经支持c++的指针和引用,在lua中调用的方式为:
--test.lua
a=demo1.new_intp();
demo1.intp_assign(a,2);
demo1.foo(a);
demo1.foo1(a);
demo1.delete_intp(a);
上面的%pointer_functions(type,name)也可以使用%pointer_class(type,name)替换,
只是替换之后,swig生成的Lua接口就不是上面的几个函数了,而是类似于类的结构,
如%pointer_class(int,intp)
将生成
struct intp {
intp(); // Create pointer object
~intp(); // Delete pointer object
void assign(type value); // Assign value
type value(); // Get value
type *cast(); // Cast the pointer to original type
static intp *frompointer(type *); // Create class wrapper from existing
// pointer
}
此时使用Lua脚本的调用语句也将相应变化
--test2.lua
a=demo1.intp();
a:assign(2);
demo1.foo(a);
demo1.foo1(a);
由此可见,在Lua中指针和引用的使用实际上没有区别,底层最后都会转化为指针后进行操作
二、数组
c++中经常会使用到数组,因此swig在生成Lua接口是也提供了对数组的支持,例子如下:
//demo1.h
void foo(double arr[]);
--demo1.i
%module demo1
%{
#include "demo1.h"
%}
%include "carrays.i"
%array_functions(double, doubleArray);
这里的%include "carrays.i"
是指导入swig提供的库,而%array_functions(type,name)
将会生成一组Lua接口提供调用:
1、type *new_name(int nelements)
2、type *delete_name(type *ary)
3、type name_getitem(type *ary, int index)
返回type的值 ary[index].
3、void name_setitem(type *ary, int index, type value)
给ary[index]赋值
同样的,也有一个%array_class(type,name)
的操作可以生成类结构
struct name {
name(int nelements); // Create an array
~name(); // Delete array
type getitem(int index); // Return item
void setitem(int index, type value); // Set item
type *cast(); // Cast to original type
static name *frompointer(type *); // Create class wrapper from
// existing pointer
};
其在Lua中的调用方式随使用的语句的不同而不同,读者可以根据生成的接口自己写lua测试代码测试。
需要注意的是这里的两组语句:%pointer_functions(type,name)
、%pointer_class(type,name) 、
%array_functions(type,name)
、
%array_class(type,name)` 都不能用于char*和char**,否则
将是不安全、不负责任的。
参考文献:1、http://www.swig.org/Doc3.0/SWIGDocumentation.html#Library_nn4
2、http://www.swig.org/Doc3.0/SWIGDocumentation.html#Library_carrays
3、http://blog.youkuaiyun.com/u010640235/article/details/52073130