Lua学习笔记五

转载 2013年12月05日 19:37:51

Lua学习笔记五

通过前面4次的学习,我们已经具备了一些基本知识:
1、使用Lua脚本语法
2、编写Lua函数和C函数,并使他们交互
3、表和其他类型的参数的应用
4、处理函数的返回值的方法
很好,很强大。这些知识足以开启Lua世界的大门,现在让我们来真正的进入Lua的世界。

本节的目的:写一套操作动态浮点数组的函数,并把他们封装成库,侧重点为编写函数库的基本套路。 


读到这里可以发现,该系列文章是从开发者的角度来进行Lua学习,而不是一般文章中介绍Lua语法和如何编写Lua脚本的角度。事实上我也正有此意--把以前的工作全部封装成Lua接口,然后只要懂得Lua脚本语法的人,就可以参与到我们的项目里来。

 


 

记得上节我们写的2个Lua脚本函数吗?他们是:

NewWindow = CreateWindow{ x = 0,y = 0, w = 1024, h = 768} ;
AddButton{hWindow = NewWindow , x =100, y = 100, w = 75, h = 25};

但是他们还不够好,以下的方式更符合我们习惯:

NewWindow = Object.CreateWindow();
Object.AddCompent{ Type = Button, HWND = NewWindow, x = 100, y = 100, w = 75, h = 25};
Object.Show(NewWindow);
Object.Destory(NewWindow);

这个Object 就是我们封装了一套处理窗体操作的函数库。
当然,我不能给出Object库的代码,因为它太大了。不过,让我们来写一套操作动态浮点数组的函数,并把他们封装成库吧。


 RTFS,RTFS,RTRTRTFS~~

-------以下是Lua脚本--------
--test.lua
function f( x, y)
 return x + y
end

LuaC_MessageBox( "Hello World!");

--这三句是普通的函数交互,因为不能在你们的代码中通过,所以注释起来。
--NewWindow = CreateWindow{ x = 0, y = 0, w = 1024, h = 768} ;
--AddButton{hWindow = NewWindow , x =100, y = 100, w = 75, h = 25};
--ShowWindow( NewWindow);

--这是我下个要实现的目标,暂时没找到方法。
--NewWindow.add_button{ x = 100, y = 100, w = 40, h = 18, dp2 = "button1"}
--NewWindow.add_bitmap{ x = 0, y = 0, w = 640, h 480}

--这两句是基于函数库的语法。
NewObject = object.new( 8);
LuaC_MessageBox( object.count(NewObject)); 

//------------以下是test.cpp文件----------------
// 由于总是在上一次的基础上进行的添加,因此已经实现过了的函数体我就省略了。
// 这也是与“给出完整可编译代码段”的原则的妥协---不然代码就太多了。
// 这次的代码可以编译通过,我移除了Allegro相关的东西。因为Userdata的尝试是在那个环境下
// 测试的,所以才用它举例。为了保持通用性和“给出完整可编译代码段”的原则,我会尽量用
// 原生态的例子来阐述问题。

//================================================================================================================
//           Lua Test Object
//           C++ Source lua_test.cpp
//================================================================================================================
//================================================================================================================
//           Include Files
//================================================================================================================
extern "C"
{
 #include "D://My Documents//Visual Studio 2005//Projects//lua//lua//lua.h"
 #include "D://My Documents//Visual Studio 2005//Projects//lua//lua//lualib.h"
 #include "D://My Documents//Visual Studio 2005//Projects//lua//lua//lauxlib.h"
}

#include <windows.h>
#include <stdio.h>
#include <string>
using namespace std;
//================================================================================================================
//           Libraries
//================================================================================================================
#pragma comment( lib ,"D://My Documents//Visual Studio 2005//Projects//lua//release//lua.lib")
//================================================================================================================
//           Type Define
//================================================================================================================
typedef struct MyStruct_TAG
{
 int   count;
 double _array[1];
}MyStruct,*MyStruct_PTR;

//================================================================================================================
//           Global Variables
//================================================================================================================
lua_State *L;
//================================================================================================================
//           Lua Functions
//================================================================================================================
double f( double x, double y )
{
  // 已经实现
}
//================================================================================================================
//           C/C++ Functions
//================================================================================================================
int LuaC_MessageBox( lua_State *L)
{
   // 已经实现
}

int LuaC_GetObject( lua_State* L)
{
 // LuaC_GetObject( object, index)
 // 获取第1个参数
 MyStruct_PTR object = (MyStruct_PTR)lua_touserdata(L, 1);
 // 获取第2个参数
 int index = luaL_checkint( L, 2);
 // 参数有效性判断
 luaL_argcheck(L, object != NULL, 1, "`object expected");
 luaL_argcheck(L, 1 <= index && index <= object->count, 2, "index out of range");
 // 返回值压栈
 lua_pushnumber(L, object->_array[index - 1]);
 // 设置返回参数个数
 return 1;
}

 

int LuaC_CreateObject( lua_State *)
{
 int   count;
 size_t size;
 void*  lp;

 // LuaC_CreateObject(1000)
 // 获取参数
 count = luaL_checkint(L, 1);
 // 计算大小
 size = sizeof(MyStruct) + (count - 1) * sizeof( double);
 // 申请空间
 lp = lua_newuserdata( L, size);
 // 初始化
 memset( lp, '/0',size);
 // 设置个数
 ((MyStruct_PTR)lp)->count = count;

 // 设置返回值个数
 return 1;
}

int LuaC_SetObject(lua_State *L)
{
 // LuaC_SetObject( object, value, index)
 // 获取第1个参数
 MyStruct_PTR object = (MyStruct_PTR)lua_touserdata(L, 1);
 // 获取第2个参数
 double value = luaL_checknumber( L, 2);
 // 获取第3个参数
 int index = luaL_checkint( L, 3);
 // 参数有效性判断
 luaL_argcheck(L, object != NULL, 1, "`object expected");
 luaL_argcheck(L, 1 <= index && index <= object->count, 2, "index out of range");
 // 执行逻辑
 object->_array[index - 1] = value;

 // 设置返回参数个数
 return 0;
}

 

int LuaC_GetCount( lua_State* L)
{
 // LuaC_GetCount( object)
 // 获取第1个参数
 MyStruct_PTR object = (MyStruct_PTR)lua_touserdata(L, 1);
 // 参数有效性判断
 luaL_argcheck(L, object != NULL, 1, "`object expected");
 // 返回值压栈
 lua_pushnumber(L, object->count);
 // 设置返回参数个数
 return 1;
}

// 初始化库
static const struct luaL_reg object_lib[] =
{
 {"new",   LuaC_CreateObject},
 {"set",   LuaC_SetObject},
 {"get",   LuaC_GetObject},
 {"count",  LuaC_GetCount},
 {NULL, NULL}
};

int _luaopen_object (lua_State *L)
{
 luaL_openlib(L, "object", object_lib, 0);
 return 1;
}
//================================================================================================================
//           Main Functions
//================================================================================================================
int main( void)
{

 int error;

 L = lua_open();
 luaopen_base(L);
 luaL_openlibs(L);
 // 自己的扩展库
 _luaopen_object(L);

 // 注册C/C++函数
 lua_register( L, "LuaC_MessageBox", LuaC_MessageBox); 

 //luaopen_table(L);
 //luaopen_io(L);
 //luaopen_string(L);
 //luaopen_math(L);

 /*
 while( fgets( buff, sizeof( buff), stdin ) != NULL)
 {
  error = luaL_loadbuffer( L, buff, strlen(buff),"line") || lua_pcall( L,0,0,0);
  if ( error )
  {
   fprintf( stderr, "%s", lua_tostring( L, -1));
   lua_pop( L, 1);
  }
 }
 */
 // load the script
 if ( (error = luaL_dofile(L, "test.lua")) != 0)
 {
  allegro_message( "error!!");
  return 0;
 }
 /*
 double ret = f( 10, 3.4);
 printf( "ret = %f", ret);

 getchar();
 */
 lua_close( L);
 return 1;
}
END_OF_MAIN();

 


 

代码里面的注释越来越多了,不是吗?很多时候就是这个样子样,看代码比看文字要来的直接。

新出现了很多Lua库函数调用,不过都是涉及参数有效性检测的函数。所以如果你不了解用法的话,最好查找《Lua参考手册》。另外,记得下载的Lua源码吗?在名为“doc”的文件夹里有一个contents.html,打开看看吧。

好了,现在让我们把注意力转回今天的重点。

写一个自己的库的步骤是:

1、写一套功能函数,如:
int LuaC_CreateObject( lua_State *)
int LuaC_SetObject(lua_State *L)
int LuaC_GetObject(lua_State *L)
int LuaC_GetObjectCount(lua_State *L)

在这个步骤里,与编写普通的C/Lua交互函数没有什么区别。

2、声明一个Lua表,作为函数库,如:
// 初始化库
static const struct luaL_reg object_lib[] =
{
 {"new",   LuaC_CreateObject},
 {"set",   LuaC_SetObject},
 {"get",   LuaC_GetObject},
 {"count",  LuaC_GetCount},
 {NULL, NULL}
};

注意上面的粗体,声明一个作为库的表,需要使用关键字 Static const
另外这个结构体 struct luaL_reg:
typedef struct luaL_Reg {
  const char *name;
  lua_CFunction func;
} luaL_Reg;
作为库的表实际上就是一个luaL_Reg类型的数组。Lua中其他一些标准库也都是按照这个规矩来定义的。
最后这个数组需要使用一个哑员(空值)来作为结束符。

3、调用luaL_openlib();函数,如:

int _luaopen_object (lua_State *L)
{
 luaL_openlib(L, "object", object_lib, 0);
 return 1;
}

在这里,我把这个函数封装了一下,只是为了风格统一。另外,在所有我自己写的类似Lua原有函数的函数前面我都加了下划线,为了几个月后让我明白:这是我自己写的,而不是Lua自己带的。另外,这是跟Andre LaMothe学的。

4、在main函数里加载库。如:

 // 自己的扩展库
 _luaopen_object(L);

 

OK.以上就是编写自己的库的基本套路。
如果一切正常的话,会弹出一个对话框,告诉你刚刚申请的数组对象有8个元素。

好了,下一个笔记可能会是  “面向对象”、“Weaktable(弱表)”、“lightuserdata的应用”、“Metatable(元表)”、4个内容中的一个或几个。如果你学习的够快的话,代替我来写这些内容吧``

lua学习笔记

  • 2014年03月05日 11:15
  • 13KB
  • 下载

Lua学习笔记(五) —— 非抢先式的多线程

1、 概念 协同程序提供一种协作式的多线程。每个协同程序都等于是一个线程。一对yield-resume可以将执行权在不同线程之间切换。然而,协同程序与常规的多线程的不同之处在于,协同程序是非抢先式的...

Lua 学习笔记(五) —— 语句

一、赋值 多重赋值: 每个值或每个变量之间以逗号分隔 例如:a, b = 10, 20 Lua先对等号右边的所有元素求值,然后才执行赋值。 二、局部变量和块 local创建局部变量,作用域仅...

12.lua学习笔记:环境

Lua将其所有的全局变量保存在一个常规的table中,这个table被称为“环境”。它被保存在全局变量_G中。     1. 全局变量声明:     Lua中的全局变量不需要声明就可以使用。尽管很方便...

用lua写Android界面学习笔记

问题描述: 有时候我们的app可能需要动态的更新一个页面,不只是单纯的内容,有可能布局也要改变,所以就考虑到开发过程中用lua脚本动态加载的Android页面,以便可以不重新发布apk,通过服务端控制...
  • AuthorK
  • AuthorK
  • 2016年01月14日 15:24
  • 3066

cocos-lua学习笔记(六)一个简单的Button

注意:使用版本为3.7.1版本,最新版本。 旧版本使用cc.ui,新版本直接使用ccui。 local MainScene = class("MainScene", functio...

Lua 学习笔记(二) —— Scite 的配置文件讲解

Scite的配置文件ru SciTEGlobal.properties 全局配置文件,一般不去改动 SciTEUser.properties 用户配置文件,对全局配置要改动的地方,都写在这个文...

2.lua学习笔记:调试、运行

一:运行方式     1.在命令行中输入lua,进入lua解释器,输入命令这样就能和运行Python解释器一样操作     2.编写lua脚本,在命令行中输入lua  tmp.lua即可运行tmp.l...

lua学习笔记---选择,循环语句

转载自:http://blog.csdn.net/jarlen/article/details/43813543 选择语句 形式: 1> if 条件 then 分支 end ...

Lua学习笔记 第二章 类型与值

lua是一种动态类型语言;lua中的8种基础类型是: nil, boolean, number, string, userdata, function,thread, table 函数type()...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Lua学习笔记五
举报原因:
原因补充:

(最多只允许输入30个字)