用LuaBridge为Lua绑定C/C++对象
作者:网络转载 发布时间:[ 2014/4/2 9:37:22 ] 推荐标签:C++ Lua 编程
按下面方式注册:
<span style="font-size:14px;"> getGlobalNamespace (L)
.beginNamespace ("test")
.beginClass<A>("A")
.addConstructor <void (*) (void)> ()
.addStaticData ("staticData", &A::staticData)
.addStaticProperty ("staticProperty", &A::getStaticData)
.addStaticFunction ("getStaticProperty", &A::getStaticProperty) //read-only
.addStaticCFunction ("staticCFunc", &A::staticCFunc)
.addData ("data", &A::dataMember)
.addProperty ("prop", &A::getProperty, &A::setProperty)
.addFunction ("func1", &A::func1)
.addFunction ("virtualFunc", &A::virtualFunc)
.addCFunction ("cfunc", &A::cfunc)
.endClass ()
.deriveClass<B, A>("B")
.addConstructor <void (*) (void)> ()
.addData ("data", &B::dataMember2)
.addFunction ("func1", &B::func1)
.addFunction ("func2", &B::func2)
.endClass ()
.endNamespace ();</span>
注册后,可以再Lua脚本中按一下方式使用:
<span style="font-size:14px;"> local AClassObj = test.A () --create class A instance
print("before:",test.A.staticData) -- access class A static member
test.A.staticData = 8 -- modify class A static member
print("after:",test.A.staticData)
print("before:", test.A.getStaticProperty())
--test.A.staticProperty = 1.2 --error:can not modify
print("staticCFunc")
test.A.staticCFunc()
AClassObj.data = "sting"
print("dataMember:",AClassObj.data)
AClassObj.prop = 'a'
print("property:",AClassObj.prop)
AClassObj:func1()
AClassObj:virtualFunc()
AClassObj:cfunc()
BClassObj = test.B()
BClassObj:func1()
BClassObj:func2()
BClassObj:virtualFunc() </span>
其输出结果为:
<span style="font-size:14px;"> A constructor
before: 3
after: 8
before: 0.5
staticCFunc
dataMember: sting
property: a
func1 In Class A
virtualFunc In Class A
cfunc In Class A
A constructor
B constructor
func1 In Class B
func2 In Class B
virtualFunc In Class B</span>
类的方法注册类似于通常的函数注册,虚函数也是类似的,没有特殊的语法。在LuaBridge中,能识别const方法并且在调用时有检测的,因此如果一个函数返回一个const object或包含指向const object的数据给Lua脚本,则在Lua中这个被引用的对象则被认为是const的,它只能调用const的方法。对于每个类,析构函数自动注册的。无须在继承类中重新注册已在基类中注册过的方法。If a class has a base class that is **not** registeredwith Lua, there is no need to declare it as a subclass.
Constructors
为了在Lua中,创建类的对象,必须用addConstructor为改类注册构造函数。并且LuaBridge不能自动检测构造函数的参数个数和类型(这与注册函数或方法能自动检测是不同的),因此在用注册addConstructor时必须告诉LuaBridge在Lua脚本将用到的构造函数签名,例如:
<span style="font-size:14px;"> struct A {
A ();
};
struct B {
explicit B (char const* s, int nChars);
};
getGlobalNamespace (L)
.beginNamespace ("test")
.beginClass <A> ("A")
.addConstructor <void (*) (void)> ()
.endClass ()
.beginClass <B> ("B")
.addConstructor <void (*) (char const*, int)> ()
.endClass ();
.endNamespace ()</span>
在Lua中,可以一些方式,创建A和B的实例:
<span style="font-size:14px;"> a = test.A () -- Create a new A.
b = test.B ("hello", 5) -- Create a new B.
b = test.B () -- Error: expected string in argument 1</span>
lua_State*
有时候绑定的函数或成员函数,需要lua_State*作为参数来访问栈。使用LuaBridge,只需要在将要绑定的函数后添加lua_State*类型的参数即可。比如:
<span style="font-size:14px;"> void useStateAndArgs (int i, std::string s, lua_State* L);
getGlobalNamespace (L).addFunction ("useStateAndArgs", &useStateAndArgs); </span>
在Lua中,可按以下方式使用:
<span style="font-size:14px;"> useStateAndArgs(42,"hello")</span>
在脚本中,只需传递前面两个参数即可。注意 lua_State*类型的参数放在定义的函数后,否则结果是未定义的。
Class Object Types
一个注册的类型T,可能以下方式传递给Lua脚本:
<span style="font-size:14px;"> `T*` or `T&`: Passed by reference, with _C++ lifetime_.
`T const*` or `T const&`: Passed by const reference, with _C++ lifetime_.
`T` or `T const`: Passed by value (a copy), with _Lua lifetime_.</span>
C++ Lifetime
对于C++ lifetime的对象,其创建和删除都由C++代码控制,Lua GC不能回收这些对象。当Lua通过lua_State*来引用对象时,必须确保该对象还没删除,否则将导致未定义的行为。例如,可按以下方法给Lua传递
C++ lifetime的对象:
<span style="font-size:14px;"> A a;
push (L, &a); // pointer to 'a', C++ lifetime
lua_setglobal (L, "a");
push (L, (A const*)&a); // pointer to 'a const', C++ lifetime
lua_setglobal (L, "ac");
push <A const*> (L, &a); // equivalent to push (L, (A const*)&a)
lua_setglobal (L, "ac2");
push (L, new A); // compiles, but will leak memory
lua_setglobal (L, "ap");
</span>
Lua Lifetime
当C++通过值传递给Lua一个对象时,则该对象是Lua lifetime。在值传递时,该对象将在Lua中以userdata形式保存,并且当Lua不再引用该对象时,该对象可以被GC回收。当userdata被回收时,其相应对象的
析构函数也会被调用。在C++中应用lua lifetime的对象时,必须确保该对象还没被GC回收,否则其行为是未定义的。例如,可按以下方法给Lua传递的是Lua lifetime的催下:
<span style="font-size:14px;"> B b;
push (L, b); // Copy of b passed, Lua lifetime.
lua_setglobal (L, "b");</span>
当在Lua中调用注册的构造函数创建一个对象时,该对象同样是Lua lifetime的,当该对象不在被引用时,GC会自动回收该对象。当然你可以把这个对象引用作为参数传递给C++,但需要保证C++在通过引用使用该对象时,
改对还没有被GC回收。
Pointers, References, and Pass by Value
当C++对象作为参数从Lua中传回到C++代码中时,LuaBridge会尽可能做自动转换。比如,向Lua中注册了以下C++函数:
<span style="font-size:14px;"> void func0 (A a);
void func1 (A* a);
void func2 (A const* a);
void func3 (A& a);
void func4 (A const& a);</span>
则在Lua中,可以按以下方式调用上面的函数:
<span style="font-size:14px;"> func0 (a) -- Passes a copy of a, using A's copy constructor.
func1 (a) -- Passes a pointer to a.
func2 (a) -- Passes a pointer to a const a.
func3 (a) -- Passes a reference to a.
func4 (a) -- Passes a reference to a const a. </span>
上面所有函数,都可以通过a访问对象的成员以及方法。并且通常的C++的继承和指针传递规则也使用。比如:
<span style="font-size:14px;"> void func5 (B b);
void func6 (B* b); </span>
在lua中调用:
<span style="font-size:14px;"> func5 (b) - Passes a copy of b, using B's copy constructor.
func6 (b) - Passes a pointer to b.
func6 (a) - Error: Pointer to B expected.
func1 (b) - Okay, b is a subclass of a. </span>
当C++给Lua传递的指针是NULL时,LuaBridge会自动转换为nil代替。反之,当Lua给C++传递的nil,相当于给C++传递了一个NULL指针。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11