<使用了聚合的类的导出> 聚合是最常见的构造新类的方式了,另一个是继承。tolua++支持单继承,后面会提到继承的例子。这里先看看怎么将利用了聚合的类导出到lua中。 我的目的是想在Lua中使用C++类的实例,而不是在lua中生成C++类实例,所以我在利用tolua++向lua导出类时一般不导出构造函数,这样就无法在lua中生成类实例。 但是为了演示的方便,这个例子中用到的两个简单类CNumber和CMessage仍然导出了构造函数。 另外一个单件(singleton)CTestSystem的构造函数、拷贝构造函数、=操作符都被声明为protected,在向lua导出时只导出了几个方法。你无法在lua中生成它的实例,即便在C++中也不行,只能通过其静态成员函数GetSingleton()获取。 实际的头文件classg.h如下:
接下来是pkg文件:
我只导出需要的部分。有点遗憾的是,tolua++的手册中说无法通过"@"修改你要导出的类的名字,这样的话,如果我想在lua中使用另外的名字,就要用别的办法了(文档中说$renaming可以,未试验,存疑)。 驱动部分和之前的例子中类似:
一直没有介绍上面用到的几个函数。在lua5.1中,用来生成lua状态对象的lua_open函数不再直接可用,替换为lua_newstate,不过lua_newstate要提供内存分配函数,lua扩展库提供了无参数的luaL_newstate,用起来方面。同时为了向前兼容,还做了宏定义#define lua_open luaL_newstate()。所以你仍然可以用lua_open来或者lua_State,但是要注意这里只是个宏。 luaopen_base()打开基本的库。 tolua_classgroup_open是tolua++生成的函数,用来向lua导出你定义的类和其它变量及函数。 luaL_dofile也是宏定义,用来加载并执行一个脚本文件,在lauxlib.h中定义。 lua_close关闭之前打开的状态块。 关于这些函数的详细说明,请参考
lua5.1在线文档
。 下面是classgroup.lua文件:
OK,这是个简单的例子,我们只用到了tolua++最基本的东西,进一步的研究学习可以琢磨它的文档。但是我用luaplus想做到这一点,费了不少力气。相对luaplus,tolua++在导出类到lua方面更为方便好用,而luaplus用来访问lua脚本则比tolua++方便(隔离了繁琐的虚拟栈操作)。两个封装的侧重点不同,如果可以结合起来,会非常有趣,双向的访问都很方便。有时间的话我会尝试一下。 接下来会试验一下单继承。 ==**== 刚才试验了下$renaming 可以用。在pkg后加入$renaming CTestSystem @ lSystems,用tolua++编译,然后编译工程,则必须修改classgroup.lua,
将singleton
=
CTestSystem:GetSingleton();改为
singleton
=
lSystems:GetSingleton();。
#ifndef_CLASSGROUP_H
#define
_CLASSGROUP_H
#include
<
string
.h
>
class
CNumber
{
//
tolua_export
public
:
//
tolua_begin
CNumber():m_nNum(
0
)
{
}
CNumber(
int
num):m_nNum(num)
{
}
~
CNumber()
{
}
void
SetNumber(
int
num)
{
m_nNum
=
num;
}
int
GetNumber()
{
return
m_nNum;
}
int
Add(
int
num)
{
m_nNum
+=
num;
return
m_nNum;
}
//
tolua_end
protected
:
int
m_nNum;
}
;
//
tolua_export
//
tolua_begin
class
CMessage
{
//
tolua_end
public
:
//
tolua_begin
CMessage()
{
strcpy(m_szMessage,
"
initialmessage
"
);
}
CMessage(
char
*
initmsg)
{
if
(initmsg)
strncpy(m_szMessage,initmsg,
256
);
}
~
CMessage()
{
}
void
SetMessage(
char
*
msg)
{
if
(msg)
{
strncpy(m_szMessage,msg,
256
);
}
}
char
*
GetMessage()
{
return
m_szMessage;
}
void
ShowMessage()
{
printf(
"
thismessageisprintedinc++codewhenluacallShowMessage:%s
"
,m_szMessage);
}
//
tolua_end
protected
:
char
m_szMessage[
256
];
}
;
//
tolua_export
class
CTestSystem
{
public
:
static
CTestSystem
&
GetSingleton()
{
static
CTestSystemsys;
return
sys;}
CNumber
&
GetNumberObj()
{
return
m_Number;}
CMessage
&
GetMessageObj()
{
return
m_Message;}
protected
:
CTestSystem()
{}
CTestSystem(
const
CTestSystem
&
);
CTestSystem
&
operator
=
(
const
CTestSystem
&
rhs);
~
CTestSystem()
{}
private
:
CNumberm_Number;
CMessagem_Message;
}
;
#endif
$#include
"
classg.h
"
class
CNumber
{
//
tolua_export
public
:
//
tolua_begin
CNumber();
CNumber(
int
num);
~
CNumber(
void
);
void
SetNumber(
int
num);
int
GetNumber(
void
);
int
Add(
int
num);
//
tolua_end
}
;
//
tolua_export
//
tolua_begin
class
CMessage
{
//
tolua_end
public
:
//
tolua_begin
CMessage(
void
);
CMessage(
char
*
initmsg);
~
CMessage(
void
);
void
SetMessage(
char
*
msg);
char
*
GetMessage();
void
ShowMessage();
//
tolua_end
}
;
//
tolua_export
class
CTestSystem
{
static
CTestSystem
&
GetSingleton();
CNumber
&
GetNumberObj();
CMessage
&
GetMessageObj();
}
;
#include
"
classg.h
"
#include
"
lua.hpp
"
int
tolua_classgroup_open(lua_State
*
);
int
_tmain(
int
argc,_TCHAR
*
argv[])
{
lua_State
*
L
=
luaL_newstate();
luaopen_base(L);
tolua_classgroup_open(L);
luaL_dofile(L,
"
../scripts/classgroup.lua
"
);
lua_close(L);
return
0
;
}
print(
"
nowinclassgroup.lua!
"
)
print(
"
gettheCTestSystemsingleton,callGetNumberObjandGetMessageObj:
"
)
singleton
=
CTestSystem:GetSingleton();
print(singleton)
numobj
=
singleton:GetNumberObj();
print(numobj)
msgobj
=
singleton:GetMessageObj();
print(msgobj)
--
accessCNumberandCMessage
print(
"
initnumobj'snumber:
"
..numobj:GetNumber());
numobj:SetNumber(
100
);
print(
"
aftercallnumobj:SetNumber(100),changednumber:
"
..numobj:GetNumber())
print(
"
initmsgobj'smessage:
"
..msgobj:GetMessage());
msgobj:SetMessage(
"
Thismessageissetinluascript
"
);
print(
"
newmessage:
"
..msgobj:GetMessage())
msgobj:ShowMessage()