DELPHI中集成LUA脚本学习笔记1_初探LUA

这篇博客介绍了如何在DELPHI中集成LUA脚本,作者选择LUA因其小巧且易于扩展。文章通过一个简单的LUA脚本示例展示了如何在Delphi程序中加载、执行脚本,调用脚本函数,以及脚本调用主程序函数。博主还提供了一个TNpc类的代码实现,用于演示如何在Delphi中与LUA交互,并强调了在脚本中调用主程序函数时返回参数的处理方式。

序:记得在刚开始学编程的时候,知道了一个字符串并不是一定要在程序中固定死的,而是可以用TEdit.Text来连接的,于是有了一个想法,把一整段代码(几个函数)放在Memo中,想在程序运行的时候通过修改Memo中的内容而让程序能灵活使用.可惜后来失败了.大家看到这一定会笑的半死.的确这是一个很幼稚的想法.后来知道用脚本可以实现程序的灵活运行,可惜一直没有时间研究,这几天刚好要用到脚本,所以研究了一下午,顺便写一点心得.

Python,LUA等都不错,我选择了LUA原因是连接库比较小,扩展方便而Python太庞大了.wow就是使用LUA做为引擎.LUA本是C/C++的连接库,网上有pas的dll连接单元.我是用Delphi来集成的.

LUA的语法类似C,在网上可以找到.具体的使用方法可以见 云风大侠的翻译的手册
http://www.codingnow.com/2000/download/lua_manual.html
脚本示例:

nNum = Num()
function Add(number)
 number = number + nNum
 return number
end

以上是一个简单的LUA脚本,其中有一个变量nNum和一个函数Add.函数Add的功能是将传入的number+nNum然后返回.nNum的值为调用主程序中的Num函数获得.
LUA要集成到程序中,最基本的要知道一下几点.
1.脚本加载执行.
2.主程序调用脚本中函数.
3.脚本调用主程序函数
4.主程序于脚本变量相互获取

我写了一个简单的类代码如下:
view plaincopy to clipboardprint?
TNpc  = class 
    l: p_lua_state;     
    FileName : string;  
public 
    constructor Create(sName:string);  
    destructor Destroy;  
    procedure Initialize();  
    procedure run();  
end;  
 
function lua_Num(l: p_lua_state): integer; cdecl;  
begin 
    lua_pushnumber(l,30);  //返回值30压栈  
    result := 1;            //定义返回参数的数量并不是具体值,此时为1 个  
end;  
 
constructor TNpc.Create(sName:string);                            
begin 
    FileName := sName;  
    l := lua_open();      
    lua_baselibopen(l);// LUA 内嵌 BASE 库  
end;  
destructor TNpc.Destroy;  
begin 
    lua_close(l);  
end;  
procedure TNpc.Initialize();  
begin 
    lua_register(l, 'Num', lua_Num);  //将主程序中的lua_Num函数注册到引擎中,让脚本用Num来调用  
    luaL_loadfile(l, Pchar(FileName)); //加载脚本  
end;  
 
procedure TNpc.run();  
begin 
    lua_resume(L,0);            //脚本使用luaL_loadfile加载时要用lua_resume来返回运行.  
    lua_getglobal(L, 'add');   //掉用脚本中函数的名称  
    lua_pushnumber(L, 100); //将脚本中add函数使用的参数压栈  
    lua_pcall(L, 1, 1,0); //调用函数,有一个参数,一个返回值  
    Form1.Memo1.Lines.Add(lua_tostring(L,1));//返回的参数  
end;  
 
procedure TForm1.Button1Click(Sender: TObject);  
begin 
    if npc1 <> nil then npc1.Destroy; //防止内存占用  
    npc1 := TNpc.Create('npc1.lua'); //创建时传入脚本文件名  
    npc1.Initialize; //初始化  
    npc1.run;      //运行  
end; 
TNpc  = class
    l: p_lua_state;  
    FileName : string;
public
    constructor Create(sName:string);
    destructor Destroy;
    procedure Initialize();
    procedure run();
end;

function lua_Num(l: p_lua_state): integer; cdecl;
begin
    lua_pushnumber(l,30);  //返回值30压栈
    result := 1;            //定义返回参数的数量并不是具体值,此时为1 个
end;

constructor TNpc.Create(sName:string);                         
begin
    FileName := sName;
    l := lua_open();   
    lua_baselibopen(l);// LUA 内嵌 BASE 库
end;
destructor TNpc.Destroy;
begin
    lua_close(l);
end;
procedure TNpc.Initialize();
begin
    lua_register(l, 'Num', lua_Num);  //将主程序中的lua_Num函数注册到引擎中,让脚本用Num来调用
    luaL_loadfile(l, Pchar(FileName)); //加载脚本
end;

procedure TNpc.run();
begin
    lua_resume(L,0);            //脚本使用luaL_loadfile加载时要用lua_resume来返回运行.
    lua_getglobal(L, 'add');   //掉用脚本中函数的名称
    lua_pushnumber(L, 100); //将脚本中add函数使用的参数压栈
    lua_pcall(L, 1, 1,0); //调用函数,有一个参数,一个返回值
    Form1.Memo1.Lines.Add(lua_tostring(L,1));//返回的参数
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
    if npc1 <> nil then npc1.Destroy; //防止内存占用
    npc1 := TNpc.Create('npc1.lua'); //创建时传入脚本文件名
    npc1.Initialize; //初始化
    npc1.run;      //运行
end;


特别注意的是脚本中调用主程序函数时,返回参数的设置,程序中默认返回result在脚本引擎中会认为是返回参数的数量,并不是具体的值,而值要先压入栈中才可以.
lua_pushnumber(l,30);  //返回值30压栈
result := 1; 

脚本加载运行时还可以用lua_dofile(l,FileName).上面的代码我用的是luaL_loadfile和lua_resume来配合.
因为我想让多个类实例来执行不同的脚本.而lua_dofile加载后会直接运行,而luaL_loadfile只是读取脚本到内存并不直接运行.要是运行的时候用lua_resume就可以了.

脚本运行时,是运行非函数外所以代码.函数只有在主程序或脚本函数外掉用的时候才会执行.

LUA 中变量都为全局变量,使用的时候不需要定义.而且要学习LUA的时候要了解汇编,因为函数的返回等都是在栈中保存的.

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/steve0531/archive/2009/02/16/3894495.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值