Lua学习笔记三

转载 2013年12月05日 19:36:47

Lua学习笔记三


2008.7.14

修正了 main 函数里 注册新Lua函数时候的一个笔误,感谢 mayao11 指出以上错误:)

2008.5.20

修正了 小结 里关于 lua_pop(L,-1)的错误,应该为lua_pop(L,1),感谢 aslucky  指出以上错误。


首先提一下:元旦只放一天假,比较悲惨。不过可以继续研究Lua,也不失为一种幸运。

通过上一节的知识,我们可以实现很多应用了,但是在GUI领域,实在有太多的变量--x,y,z,w,h,bitmap,algi,d1,d2,d3,dp1,dp2,dp3,whatever...,而Lua的栈默认元素上限为20个,所以必须掌握Lua特有的数据类型--表的应用。
本节的目的:在上节的基础上,加入表的应用。侧重点为用表来作为函数参数。


请不要嫌我麻烦,这个系列文章是循序渐进式,而不是手册式,所以一定要掌握之前的知识,才可以继续阅读。
另外,请快速阅读pil的语法部分(1-7章),以便对Lua语法有大概的了解,这大概会花费1天的时间。但是不要在for循环和迭代器上花费太多的时间--如果暂时不想过于深入的理解Lua,而只是看懂这些笔记的程度--那些东西会研究的,但不是现在,现在我们只是初心者而已。
OK,这是我最后一次罗嗦这个。


RTFS?!

-------以下是Lua脚本--------
--test.lua
LuaC_MessageBoxEx{ hWnd = nil,
                                            lpText = "Last is ShowMessage! This is real MessageBox!",
                                            lpCaption = "Lua Test",
                                            uType = 0}                                      --0就是MB_OK

---------通过LuaEdit语法测试才出鬼了--------------

//------------以下是test.cpp文件----------------
//================================================================================================================
//           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")
//================================================================================================================
//           Global Variables
//================================================================================================================
lua_State *L;
//================================================================================================================
//           Lua Functions
//================================================================================================================
double f( double x, double y )
{
 double ret;
 lua_getglobal( L, "f");
 lua_pushnumber( L,x);
 lua_pushnumber( L,y);
 lua_call( L, 2, 1);
 //lua_pcall( L, 2, 1, 0);

 ret = lua_tonumber( L, -1);
 //lua_pop( L, 1);
 return ret;
}
//================================================================================================================
//           C/C++ Helper Functions
//================================================================================================================
// 获取t[k](表t中字段k)的值
// 有以下的值
#define GTC_LP             0x0000      // pointer
#define GTC_INT            0x0001      // int
#define GTC_DOUBLE  0x0002      // double
#define GTC_STRING    0x0003      // char
void _lua_getfield( lua_State* L, char* key, void* ret, int type_flags)
{
 lua_pushstring( L, key);
 lua_gettable( L, -2);

 switch( type_flags)
 {
  case GTC_LP:
  {
    ret = (void*)lua_topointer(L,-1);
    break;
  }
  case GTC_INT:
  {
   (*(int*)ret) = (int)lua_tointeger( L, -1);
   break;
  }
  case GTC_DOUBLE:
  {
   (*(double*)ret) = lua_tonumber( L, -1);
   break;
  }
  case GTC_STRING:
  {
   // 此处有隐患,应该阅读lua_tostring()原型之后再来处理
   strcpy( (char*)ret, lua_tostring( L, -1));
   break;
  }
  default:
   break;
 }
 lua_pop( L, 1);
}

//================================================================================================================
//           C/C++ Functions
//================================================================================================================
int LuaC_MessageBox( lua_State *L)
{
 char Message[256] = "";
 int i;

 // 获取参数个数
 int n = lua_gettop(L);

 // 保存全部参数
 for ( i = 1, j = 0; i <= n ; i++)
 {
  if( lua_isstring( L, i))
   strcpy( Message, lua_tostring( L, i));
 }

 // 执行逻辑
 MessageBox( NULL, Message, "Lua Test", MB_OK );

 // 返回值压栈

 // 返回压栈参数的个数
 return 0;
}

int LuaC_MessageBoxEx( lua_State *L)
{
   HWND    hWnd;
   char       lpText[256] = "";
   char       lpCaption[256] = "";
    UINT      uType;

 // 解析表
 _lua_getfield( L, "hWnd",        &hWnd,        GTC_LP);
 _lua_getfield( L, "lpText",       &lpText,       GTC_STRING);
 _lua_getfield( L, "lpCaption", &lpCaption, GTC_STRING);
 _lua_getfield( L, "uType",       &uType,        GTC_INT);

 // 执行逻辑
 MessageBox( hWnd, lpText, lpCaption, uType);

 // 返回值压栈

 // 返回压栈参数的个数
 return 0;
}
//================================================================================================================
//           Main Functions
//================================================================================================================
int main( void)
{
 int error;

 L = lua_open();
 luaopen_base(L);
 luaL_openlibs(L);

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

// load the script 
// 加入了错误处理
 if ( (error = luaL_dofile(L, "test.lua")) != 0)
 {
  MessageBox( NULL, "出错啦:执行脚本出错!", "Lua Test", MB_OK );
  return 0;
 }
 
 getchar();
 lua_close( L);
 return 1;
}

 


 

如你所见,这2段代码是相当的熟悉,因为我直接使用上次的代码来做的修改。并且我将新添加的部分用黑体标明,以引起你的注意。所有这写新加入的代码,相应的注释里有足够的解释--除了一个帮助器函数:_lua_getfield

这一节新加的代码比较少,但是要说清楚其中的内容就不太容易了。一定要关注我用红色标记出来的部分。

1、首先注意Lua文件中的{},这是表语法。Lua语法规定,如果(LUA文件中的)函数的参数只有1个参数,并且该参数类型为一张表,就可以使用形如: 函数名{ }的形式。

2、其次是如何解析一张表。在Lua规则里,这样定义读取表元素的协议的:
Lua API 只提供了一个lua_gettable 函数, 他接受table 在栈中的位置为参数,将对应key 值出栈, 返回与key 对应的value 。我们上面的getfield 函数假定table 在栈顶, 因此,lua_pushstring 将key 入栈之后, table 在-2 的位置。返回之前, getfield 会将栈恢复到调用前的状态。(取自PIL 25.1--表操作)

这段话有点含糊不清,实际上Lua取元素的协议是:首先将一个字符串压栈,然后调用lua_gettable。
lua_gettable的实际的工作流程是:以栈顶的字符串(key)为关键字,在栈索引位置( -2)的表(table)中查询该关键字的值(value),然后将栈顶的key出栈,再将value压栈。

3、最后一个lua_pop( L, 1)的作用就是将这个返回值出栈,以保持栈的原貌。

好好理解上面被标记为粗体的文字,因为这就是表的基本应用的全部--只是基本应用。

最后,我想谈谈为什么不能通过LuaEdit的语法检测。原因很简单:LuaEdit所使用的lua库中不包含我们写的这些个函数的声明---这就是为什么我说LuaEdit跟记事本没什么区别,事实上我除了学习Lua语法的阶段使用了它,现在一直都是用记事本在写脚本。当然,在研究Lua的同时,我也会尝试研究下LuaEdit的使用--因为它长的跟VS2005很象,呃...

Lua学习笔记(1):简单入门

前言:在 jetson TX1 上安装 torch 的时候,安装了 LUA。 原因:github 上很多神经网络(例如我想用的RNN,lstm等),用的是torch框架,而torch主要得益于一个简单...
  • moses1994
  • moses1994
  • 2017年03月23日 12:02
  • 443

剑网三插件入门教程(2):在游戏中调试Lua代码

本篇教程主要介绍了在游戏中运行和调试Lua代码的方法 先说一下关于Lua语法的学习 剑三的插件是用LUA脚本语言编写的,所以想要会写插件,必须要学会Lua。写插件并不需要用到Lua的高级技巧,...
  • wdykanq
  • wdykanq
  • 2013年09月23日 01:25
  • 5887

libSVM学习笔记

目录 一、         LibSVM文件结构说明... 2 二、         LibSVM安装及测试... 2 1.下载libsvm... 2 2.解压至指定目录... 2 ...
  • yansmile1
  • yansmile1
  • 2015年12月07日 17:18
  • 546

TensorFlow官方教程学习笔记之3-用于机器学习专家学习的MNIST数据集(MNIST For ML Beginners)

```python from __future__ import absolute_importfrom __future__ import divisionfrom __future__ impor...
  • u010837794
  • u010837794
  • 2017年07月17日 22:21
  • 508

Ionic3入门

新手入门ionic教程 神奇链接
  • qq_38082661
  • qq_38082661
  • 2017年10月11日 11:57
  • 79

CAS学习笔记(三)

十、使CAS支持HTTP协议我们知道CAS SSO 是基于HTTPS协议的单点登陆,如果要用HTTP协议进行传输,那么就需要修改CAS的相关的配置文件,图了方便,但是安全性大打折扣。10.1 修改...
  • u011372122
  • u011372122
  • 2015年07月19日 19:26
  • 361

lua写三消游戏(一)

关于游戏的资源,玩法,逻辑在这份教程里面写的很清楚:http://www.tairan.com/archives/5839...
  • lyxia3271
  • lyxia3271
  • 2014年08月19日 11:10
  • 1386

剑三插件入门介绍

什么是插件 插件是一种遵循一定规范的应用程序接口编写出来的程序。 由于一个大型软件通常只由一家软件公司开发,在开发过程中,由于人手和时间的限制,这就决定了软件自身功能的局限性,而且软件的更新速度...
  • wdykanq
  • wdykanq
  • 2013年09月16日 17:45
  • 11095

Lua学习笔记(三)

1.取模操作符(%)是根据以下规则定义的:    a%b == a-floor(a/b)*b    计算结果的符号永远与第二个参数相同。x%1的结果是x得小数部分,x-x%1的结果是其整数部分,x-x...
  • zzh0923
  • zzh0923
  • 2013年10月15日 16:43
  • 499

lua 学习笔记 三 & 四

在lua中,字符串的第一个字符的索引是1,也可以使用负数索引,这样将从字符串的尾部开始计数,索引-1代表字符串最后一个字符。 %a+ (alphabet)字母 +表示匹配一个或者多个 %c...
  • u010792888
  • u010792888
  • 2015年05月31日 17:50
  • 395
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Lua学习笔记三
举报原因:
原因补充:

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