网普技术论坛 网普科技  
» 游客:   网普主页 | 注册 | 登录 | 帮助
 

<<  [1] [2]  >>
作者:
标题: 在你的游戏中应用Lua [ZT] 上一主题 | 下一主题
网普科技
网普管理员

网普科技人民公仆


积分 3080
发贴 2863
注册 2004-6-26
来自 网普科技
状态 离线
#11  在你的游戏中应用Lua(3):Using Lua in cpp(基本数据类型、指针和引用)之一

前面介绍的都是针对cpp中的内建基本数据类型,然而,即使是这样,在面对指针和引用的时候,情况也会变得复杂起来。

使用前面我们已经完成的宏lua_register_directclosure只能注册by value形式的参数的函数,当参数中存在指针和引用的时候(再强调一次,目前只针对基本数据类型):

1、 如果是一个指针,通常实现函数的意图是以这个指针传递出一个结果来。
2、 如果是一个引用,同上。
3、 如果是一个const指针,通常只有面对char*的时候才使用const,实现函数的意图是,不会改变这个参数的内容。其它情况一般都避免出现使用const指针。
4、 如果是一个const引用,对于基本数据类型来说,一般都避免出现这种情况。

Lua和cpp都允许函数用某种方式返回多个值,对于cpp来说,多个返回值是通过上述的第1和第2种情况返回的,对于lua来说,多个返回值可以直接返回:

--in Lua
function swap(x, y)
tmp = x
x = y
y = tmp

return x, y
end

x = 100
y = 200

x, y = swap(x, y)

print(x..y)

程序输出:200100

同样的,在主机程序中,我们也可以向Lua返回多个值:

int swap(lua_State *L)
{
//取得两个参数
int x = Get(TypeWrapper<int>(), L, -1);
int y = Get(TypeWrapper<int>(), L, -2);

//交换值
int tmp = x;
x = y;
y = tmp;

//向Lua返回值
Push(L, x);
Push(L, y);

    //告诉Lua我们返回了多少个值
return 2;
}

现在我们可以在Lua中这样调用这个函数:

x = 100
y = 200

x, y = swap(x, y)

在我们的register_proxy函数中只能对基本数据类型的by value方式有效,根据我们上面的分析,如果我们能够在编译期知道,对于一个模板参数T:
1、 这是一个基本的数据类型,还是一个用户自定义的数据类型?
2、 这是一个普通的指针,还是一个iterator?
3、 这是一个引用吗?
4、 这是一个const 普通指针吗?
5、 这是一个const 引用吗?

如果我们能知道这些,那么,根据我们上面的分析,我们希望:(只针对基本数据类型)
1、 如果这是一个指针,我们希望把指针所指的内容返回给Lua。
2、 如果这是一个引用,我们希望把引用的指返回给Lua。
3、 如果这是const指针,我们希望将从Lua栈中取得的参数传递给调用函数。
4、 如果这是一个const引用,我们也希望把从Lua栈中取得的参数传递给调用函数。



天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。



网普科技,优质美国主机服务!
美国Linux主机,美国虚拟主机
支持PHP+MYSQL+cPanel+EMAIL
为用户负责,拒绝反动、赌博及色情内容! QQ:126818

发送QQ消息
2007-4-6 11:10 AM
查看资料  访问主页  发短消息  QQ   编辑帖子  引用回复 顶部
网普科技
网普管理员

网普科技人民公仆


积分 3080
发贴 2863
注册 2004-6-26
来自 网普科技
状态 离线
#12  在你的游戏中应用Lua(3):Using Lua in cpp(基本数据类型、指针和引用)之二

现在首要的问题在于,我们希望通过某种方式,在编译期获得一个模板参数T是不是一个指针或者一个引用?幸运的是,boost库已经提供了这样的功能,boost提供了一组type_traits,让我们能够在编译期获取模板参数T的类型。

你可以从http://boost.sourceforge.net/index.htm ;下载boost库,我们需要的是boost的type_traits一组头文件。

下载完 boost库之后,并设置好包含路径,让我们开始修改我们的Call函数,对指针和引用做出适当的改变。
有了boost库之后,测试一个模板参数T是指针还是引用再也简单不过了:

#include <boost/type_traits.hpp>
using namespace boost;

template <typename RT, typename P1>
int Call(RT (*Func) (P1),  lua_State *L, int idx)
{
is_pointer<P1>::value || is_reference<P1>::value;
}

现在我们已经能够得到一个bool值,如果这个值为真,我们并不试图从lua栈中获取这样的参数,而是首先将它交给调用函数处理,然后再作为返回值交给lua,并且返回的时候,是返回这个指针所指内容的拷贝。如果为假,我们仅仅将它作为参数交给调用函数。

为了能够做到编译期的静态分派,我们使用函数的重载机制,首先,我们需要定义一个bool到类型的映射,以区别参数的类型:

template <bool B>
struct bool2type
{
enum { value = B };
};

为了清晰起见,我们对两种形式做一个typedef:

typedef bool2type<true> ResultType;
typedef bool2type<false> NormalType;

对于一个参数来说,如果它的标志是ResultType,那么它将作为结果交给lua,如果是第二种形式,那么它仅仅交给被调函数。

现在我们要为一个参数的Call函数提供两个版本的_Call函数,以区分其指针参数调用和正常调用:

template <typename RT, typename P1>
int _Call(RT (*Func)(P1), ResultType,  lua_State *L, int idx)
{
}

template <typename RT, typename P1>
int _Call(RT (*Func)(P1), NormalType, lua_State *L, int idx)
{
}

现在我们在Call函数中可以直接交给_Call来处理:

template <typenaem RT, typename P1>
int Call(RT(*Func)(P1), lua_State *L, int idx)
{
    return _Call(*Func,
                     bool2type<is_pointer<P1>::value
                     || is_reference<P1>::value>(), L, idx);
}



天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。



网普科技,优质美国主机服务!
美国Linux主机,美国虚拟主机
支持PHP+MYSQL+cPanel+EMAIL
为用户负责,拒绝反动、赌博及色情内容! QQ:126818

发送QQ消息
2007-4-6 11:11 AM
查看资料  访问主页  发短消息  QQ   编辑帖子  引用回复 顶部
网普科技
网普管理员

网普科技人民公仆


积分 3080
发贴 2863
注册 2004-6-26
来自 网普科技
状态 离线
#13  在你的游戏中应用Lua(4):做为配置语言

任何一种语言的存在都是为了表达,做为一种动态配置的语言,Lua提供给我们非常强大也非常的灵活的表达方式。

Lua 是一种动态类型的语言,它只有几种基本的类型:nil,boolean,number,string,userdata,function,thread 和table。Nil,boolean,number,string这些与其它语言都类似。由于Lua实现了动态内存管理,所以在使用string的时候无须担心内存分配和释放问题。

在Lua中,function就是值,可以被存储在一个变量中,可以做为另一个function的参数,可以做为返回值被返回。

Userdata 表现了一块原始的内存区域,它可以被存储在变量中,在Lua中没有对userdata的预定义操作,除了赋值和相等测试。Userdata不能在Lua中创建和修改,只能通过c api来操作userdata。Userdata表现了一个句柄的概念,你可以在Lua中持有它,可以交给任何c cpi来操作它,但是不能在Lua中改变它。

Thread表现了独立执行的线程,被用来实现coroutines。

Table是Lua中唯一的数据结构,它提供给我们非同寻常的表达能力,在Lua中,你可以用Table来表现一个Array,dynamic array,List,Set,queue,map等等,所有这些都可以使用table,用一种简单的一致的方式来表达。

在Lua中,table既不是值,也不是变量,实际上,它是Lua中的对象,我们不能声明一个Table,只能通过Table的构造器创建一个Table:

A = {}

在Lua中,Table永远都是匿名的,在上面的语句中,我们创建了一个table,然后让变量A引用到这个table,这意味着,在一个引用到一个table的变量和table本身之间没有固定的关系。从下面这个例子可以看出:

A = {}

A.name = “Lua”

B = A

A = nil

print(B.name)

程序将输出”lua”而不是nil

当程序不再用到一个table时,lua内存管理器将自动释放其内存。



天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。



网普科技,优质美国主机服务!
美国Linux主机,美国虚拟主机
支持PHP+MYSQL+cPanel+EMAIL
为用户负责,拒绝反动、赌博及色情内容! QQ:126818

发送QQ消息
2007-4-6 11:11 AM
查看资料  访问主页  发短消息  QQ   编辑帖子  引用回复 顶部
茱莉娅
THE BODY SHOP美容顾问

茱莉娅美体小铺


积分 3080
发贴 2863
注册 2009-5-21
来自 茱莉娅美体小铺
状态 离线
#13  赞助商信息The body shop

茱莉娅美体小铺
茱莉娅美体小铺淘宝店
茱莉娅美体小铺


茱莉娅美体小铺淘宝店
2007-4-6 11:11 AM
查看资料  访问主页  发短消息  QQ   编辑帖子  引用回复 顶部
<<  [1] [2]  >>

可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转:  




Powered by Discuz! 2.5 © 2001-2005 Comsenz Technology Ltd.
Processed in 0.006005 second(s), 8 queries, Gzip enabled
------------------------------------------------------------------------------
本论坛属网普科技交流与技术支持论坛!
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论!
美国主机, 美国虚拟主机, cPanel+PHP+Mysql+Ftp+Email+Zend+GD2+国际域名支持
技术支持 QQ: 126818 EMail & MSN: support[AT]netpu.net
[ 联系我们 ] - [ 网普科技 ]