探索关于Lua自动绑定系统问题

移动开发 iOS
本文着重说明Lua语言的绑定实现。这门技术能够让程序员将它们的C++类暴露给Lua,但不需要了解这个系统。

关于Lua自动绑定系统问是本文要介绍的内容,因为游戏内容增长的速度远远超过了以前,所以程序员已经不能够完全控制所有代码行为了。他们需要其他游戏开发者的帮助。脚本语言在游戏里已经被用了几十年,但是现在的游戏机更能抓住它们的优点来打打提高玩家的体验。

本精粹着重说明Lua语言的绑定实现。这门技术能够让程序员将它们的C++类暴露给Lua,但不需要了解这个系统。这里介绍的工具不仅能用在C++语言里,对其他语言也有效。这种设计的核心思想是易用性、效率、内存占用和多线程的设计目标来驱动的。

1、介绍

在本精粹里介绍的绑定玉虚在Lua脚本里建立、访问和使用C++对象。举例来说,在一个singleton的类WORLD里保存了一个ENTITY类型的实力列表,下面的脚本就能够用来设置玩家的生命值。

  1. local entity = WORLD:GetEntity("player")  
  2. entity:SetHealth(50) 

在这个例子里用到的绑定是由如下的声明定义的。

  1. //in.h and class definition  
  2. SCRIPTABLE_DefineClass(WORLD)  
  3. //in.cpp  
  4. SCRIPTABLE_Class(WORLD)  
  5. {  
  6. SCRIPTABLE_ResultMethod1(GetEntity,ENTITY,std::string)  

绑定一个类就这么简单。不需要做其他任何步骤,允许程序员把C++类和自己的函数暴露给Lua,就这么简单。

2、特性

这个形同的设计目标如下:

低内存消耗;

高效率绑定;

支持C++的继承;

使用方便;

在脚本与脚本之间保证线程使用的安全。

3、函数的绑定

Lua需要一个特别借口来绑定函数。被绑定的函数必须是下面代码里定义的类型。Lua的绑定是基于堆栈的,lua_State包含了所有传到那个函数里去的参数。这些参数必须通过使用堆栈索引号 lua_to*来收集。在这个例子里,这个函数接受到的第一个参数是字符串,第二个参数是数字,返回值也是数字。关于C函数的绑定,你可以在Lua手册[Ierusalimschy06]里找到更多的相关信息。C函数的绑定是Lua绑定到C/C++的唯一一个方法,也是这个系统的基础。

  1. int bingding_method(lua_State* state)  
  2. {  
  3. const char* some_string;  
  4. double some_number,another_number;  
  5. some_string = lua_tostring(state,1);  
  6. some_number = lua_tonumber(state,2);  
  7. //在这里可以设置返回值,或者做点你需要做的事情  
  8. //另外一个数字  
  9. lua_pushnumber(state,another_number);  
  10. return 1;//假如说我们返回1  

4、在Lua里的面向对象

Lua是使用广泛的一种编程语言,功能也很强大。本精粹介绍了如何把Lua变成一个面向对象的语言。为了帮助大家用好这个功能,Lua的作者们定义了一系列的工具来给大家提供语法帮助(syntactic sugar)。下面列出我们在本系统里使用的一个。在这段代码里,the_object是一个初始的变量,这段代码模拟了this_call的函数返回。

  1. the_object:Test(5)==the_object["Test"]( the_object,5) 

面向对象的方法可以是用这种语法来实现。对象被当做关系数组,用函数名来进行索引,返回的就是你需要调用的函数。Lua里有一个机制,允许通过使用元表(metatable)来让任何类型的变量对一个数组进行交互(这事Lua5.1的特性。Lua5.0中只有表和用户数据对象才有元表)。元表是Lua里的表,这个表被分配给一个对象,这个对象包含一些特殊的字段:_index, _newindex等([Ierusalimschy06])。在那些特殊字段里设置的函数会根据情况来被调用。当一个对象被访问时,采取的如果是数组形式的访问方式,_index就被调用了。下面的代码说明了如何讲一个元表设置到一个对象上。

  1. metatable = {}  
  2. metatable._ _index = function(table,key) return key end  
  3. setmetatable(object, metatable)  
  4. test_return = object["Test"] --在元表里面调用_index函数 

Lua的内部函数类型有数字(double 或者float)、string、table、nil、function(Lua或C)、thread和(轻)用户数据。我们采用最后一个类型在Lua里保存对象。轻用户数据和用户数据稍微有点不一样。第二种完全是Lua对象,可以拥有一个元表。

5、在Lua里绑定C++对象

绑定需要几个机制:在Lua重新描述C++对象、绑定函数的保存,最后是每个C++对象绑定数据的注册。在本精粹里,我们先把整体的技术介绍给大家,稍后我们会讲解一些特别的例子。

绑定数据结构

在已经存在的现实中,绑定是直接保存在Lua里面的,而相关的绑定数据就帮存在每个脚本里。但是如果系统必须支持的脚本数量很大,那么绑定数据就回不必要的被重复保存。为了避免这样的情况发生,我们决定把绑定数据保存在C++中一个叫SCRIPTABLE_BINDING_DATA的类里。每个绑定的类都会被分配到一个索引值。

SCRIPTABLE_BINDING_DATA里包含一个记录雷鸣和类的索引号的映射,它被保存在CLassIndexTable里。然后每个类都有个映射,记录每个函数名和对应的绑定函数。MethodTable是这种映射的重组,可以根据ClassIndex Table里的值进行索引。因为delete操作符是没有名字的,所以它的绑定被存放在单独的数组里,这个数组叫做Delete Table。最后,Parent Table保存了每个类的弗雷的索引。如果某个类是没有父类的,那么Parent Table的入口就被设置了 -1

在本书附带光盘中,你可以找到一系列的副主函数,这些辅助函数能够让你访问这些映射。你可以在 scriptable_bingding_data.h文件里找到它们。

  1. class SCRIPTABLE_BINDING_DATA  
  2. {  
  3. typedef int(* BINDING_FUNCTION) (lua_State *);  
  4. std::map<std:string,int> 
  5. ClassIndexTable;  
  6. std::vector<std::map<std::string,BINDING_FUNCTION>*> 
  7. MethodTable;  
  8. std::vector<BINDING_FUNTION> 
  9. DeleteTable;  
  10. std::vector<int>;  
  11. ParentTable;  
  12. }; 

指向这个绑定数据的指针和之歌类的索引被存放在lua_State里。这个数据的空间是由luaconf.h里的LUAI_EXTRASPACE常量分配的。

小结:探索关于Lua自动绑定系统问题的内容介绍完了,希望通过本文的学习能对你有所帮助!

责任编辑:zhaolei 来源: 互联网
相关推荐

2021-08-23 10:14:20

鸿蒙HarmonyOS应用

2019-08-26 09:15:04

Android数据库安全

2011-08-24 16:59:59

LuaModule

2011-08-31 16:06:50

LuaWeb开发

2023-02-01 13:23:00

AI自动化

2011-08-25 15:51:10

Lua脚本

2011-09-06 17:37:01

LUA应用

2011-08-29 16:37:21

Lua协同线程

2011-08-25 14:03:32

UbuntuLUA安装

2011-08-23 15:34:56

Lua模式 匹配

2011-08-24 14:33:14

LUA开发环境Decoda

2011-08-25 17:25:55

LUADelphi

2021-10-26 15:31:28

自动驾驶技术安全

2011-08-24 14:14:13

LUA环境 配置

2011-08-25 16:53:42

Lua数据 交换

2011-08-25 15:21:02

Lua字符串

2011-08-23 16:37:05

Lua数学库

2011-08-23 17:33:08

LuaMetatable

2011-08-24 15:42:38

LUA源代码

2011-08-24 15:34:44

MinGWLua环境配置
点赞
收藏

51CTO技术栈公众号