序:记得在刚开始学编程的时候,知道了一个字符串并不是一定要在程序中固定死的,而是可以用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.主程序于脚本变量相互获取

我写了一个简单的类代码如下: 

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的时候要了解汇编,因为函数的返回等都是在栈中保存的.