现在的位置: 首页 > 综合 > 正文

tolua++初探(四)

2013年10月09日 ⁄ 综合 ⁄ 共 4383字 ⁄ 字号 评论关闭
<使用了聚合的类的导出>

     聚合是最常见的构造新类的方式了,另一个是继承。tolua++支持单继承,后面会提到继承的例子。这里先看看怎么将利用了聚合的类导出到lua中。
     我的目的是想在Lua中使用C++类的实例,而不是在lua中生成C++类实例,所以我在利用tolua++向lua导出类时一般不导出构造函数,这样就无法在lua中生成类实例。
    但是为了演示的方便,这个例子中用到的两个简单类CNumber和CMessage仍然导出了构造函数。
    另外一个单件(singleton)CTestSystem的构造函数、拷贝构造函数、=操作符都被声明为protected,在向lua导出时只导出了几个方法。你无法在lua中生成它的实例,即便在C++中也不行,只能通过其静态成员函数GetSingleton()获取。
    实际的头文件classg.h如下:

#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, 
"initial message");
    }

    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(
"this message is printed in c++ code when lua call ShowMessage:%s ", m_szMessage);
    }

    
//tolua_end
protected:
    
char m_szMessage[256];
}
;//tolua_export

class CTestSystem{
public:
    
static CTestSystem & GetSingleton(){static CTestSystem sys; return sys;}
    CNumber 
& GetNumberObj(){return m_Number;}
    CMessage 
& GetMessageObj(){return m_Message;}
protected:
    CTestSystem()
{}
    CTestSystem(
const CTestSystem&);
    CTestSystem 
& operator=(const CTestSystem& rhs);
    
~CTestSystem(){}
private:
    CNumber m_Number;
    CMessage m_Message;
}
;
#endif

    接下来是pkg文件:

$#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();
}
;

    我只导出需要的部分。有点遗憾的是,tolua++的手册中说无法通过"@"修改你要导出的类的名字,这样的话,如果我想在lua中使用另外的名字,就要用别的办法了(文档中说$renaming可以,未试验,存疑)。
    驱动部分和之前的例子中类似:

#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;
}

    一直没有介绍上面用到的几个函数。在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文件:

print("now in classgroup.lua!")
print(
"get the CTestSystem singleton, call GetNumberObj and GetMessageObj:")
singleton 
= CTestSystem:GetSingleton();
print(singleton)
numobj 
= singleton:GetNumberObj();
print(numobj)
msgobj 
= singleton:GetMessageObj();
print(msgobj)
--access CNumber and CMessage
print(
"init numobj's number: "..numobj:GetNumber());
numobj:SetNumber(
100);
print(
"after call numobj:SetNumber(100), changed number : "..numobj:GetNumber())
print(
"init msgobj's message: "..msgobj:GetMessage());
msgobj:SetMessage(
"This message is set in lua script");
print(
"new message: "..msgobj:GetMessage())
msgobj:ShowMessage()

     OK,这是个简单的例子,我们只用到了tolua++最基本的东西,进一步的研究学习可以琢磨它的文档。但是我用luaplus想做到这一点,费了不少力气。相对luaplus,tolua++在导出类到lua方面更为方便好用,而luaplus用来访问lua脚本则比tolua++方便(隔离了繁琐的虚拟栈操作)。两个封装的侧重点不同,如果可以结合起来,会非常有趣,双向的访问都很方便。有时间的话我会尝试一下。
    接下来会试验一下单继承。

    ==**==
    刚才试验了下$renaming 可以用。在pkg后加入$renaming CTestSystem @ lSystems,用tolua++编译,然后编译工程,则必须修改classgroup.lua,将singleton = CTestSystem:GetSingleton();改为singleton = lSystems:GetSingleton();。

抱歉!评论已关闭.