delphi调用LUA函数来处理一些逻辑

本文介绍了如何在Delphi应用程序中利用LUA脚本来处理复杂的颜色逻辑。通过提供的LUA.PAS和LUALIB.PAS文件,实现了将逻辑代码编写在LUA中,以实现更灵活的屏幕取色功能。
摘要由CSDN通过智能技术生成

替同事做了个洛奇英雄传自动染色程序,关于屏幕取色的.因为里面他对颜色的要求比较复杂,改动也比较大,于是我让他把逻辑写在 lua 脚本里面.


uses LUA, LUALIB;
function lua_CheckColor(r,g,b:Integer):Boolean;
var
Lua : TLua;
begin
  Lua := TLua.Create; 
  luaopen_debug(Lua.LuaInstance); //如果要使用debug库
//  luaopen_io(Lua.LuaInstance);
  luaopen_math(Lua.LuaInstance);// 如果要使用math库 不然就会attempt to index global 'math' (a nil value)
  luaopen_os(Lua.LuaInstance);
//  luaopen_package(Lua.LuaInstance);
  luaopen_string(Lua.LuaInstance);
  luaopen_table(Lua.LuaInstance);
  Lua.DoFile('lua_GetColor.lua');
  lua_getglobal(Lua.LuaInstance,'nogi_GetColor');
  lua_pushnumber(Lua.LuaInstance, r); //将脚本中add函数使用的参数压栈
  lua_pushnumber(Lua.LuaInstance, g); //将脚本中add函数使用的参数压栈
  lua_pushnumber(Lua.LuaInstance, b); //将脚本中add函数使用的参数压栈


  lua_pcall(Lua.LuaInstance, 3, 1,0) ;


  Result := (lua_toInteger(Lua.LuaInstance,-1) = 1);
  Lua.Free;
end;

LUA 里面的内容是这样的

function nogi_GetColor(nR,nG,nB)
	if nR <= 25 and nG <= 25 and nB <= 25 then -- 取出25以下黑色
		return 1;
	end;
	
	return 0;
end






附上我这里带的 LUA.PAS 和 LUALIB.PAS

lua.pas

{
/**
 * @package     Delphi Lua
 * @copyright   Copyright (c) 2009 Dennis D. Spreen (http://www.spreendigital.de/blog)
 * @license     http://opensource.org/licenses/gpl-license.php GNU Public License
 * @author      Dennis D. Spreen <dennis@spreendigital.de>
 * @version     1.3
 * @revision    $Id: Lua.pas 102 2009-09-30 11:39:41Z dennis.spreen $
 */

History
1.3     DS      Improved Callback, now uses pointer instead of object index
                Modified RegisterFunctions to allow methods from other class
                to be registered, moved object table into TLua class
1.2	DS	Added example on how to extend lua with a delphi dll
1.1     DS      Improved global object table, this optimizes the delphi
                function calls
1.0     DS      Initial Release

Copyright 2009  Dennis D. Spreen (email : dennis@spreendigital.de)

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
}

unit Lua;

interface

uses
  Classes,
  LuaLib;

type
  TLuaState = Lua_State;

  TLua = class(TObject)
  private
    fAutoRegister: Boolean;
    CallbackList: TList;  // internal callback list
  public
    LuaInstance: TLuaState;  // Lua instance
    constructor Create(AutoRegister: Boolean = True); overload; virtual;
    destructor Destroy; override;
    function DoFile(Filename: String): Integer; virtual;// load file and execute
    procedure RegisterFunction(FuncName: AnsiString; MethodName: AnsiString = ''; Obj: TObject = NIL); virtual; //register function
    procedure AutoRegisterFunctions(Obj: TObject);  // register all published functions
    procedure UnregisterFunctions(Obj: TObject); // unregister all object functions
  end;

implementation

type
  TProc = function(L: TLuaState): Integer of object; // Lua Function

  TCallback = class
    Routine: TMethod;  // Code and Data for the method
    Exec: TProc;       // Resulting execution function
  end;

//
// This function is called by Lua, it extracts the object by
// pointer to the objects method by name, which is then called.
//
// @param       Lua_State   L   Pointer to Lua instance
// @return      Integer         Number of result arguments on stack
//
function LuaCallBack(L: Lua_State): Integer; cdecl;
var
  CallBack: TCallBack;       // The Object stored in the Object Table
begin
  // Retrieve first Closure Value (=Object Pointer)
  CallBack := lua_topointer(L, lua_upvalueindex(1));

  // Execute only if Object is valid
  if (assigned(CallBack) and assigned(CallBack.Exec)) then
    Result := CallBack.Exec(L)
  else
    Result := 0;
end;

{ TLua }

//
// Create a new Lua instance and optionally create Lua functions
//
// @param       Boolean      AutoRegister       (optional)
// @return      TLua                            Lua Instance
//
constructor TLua.Create(AutoRegister: Boolean = True);
begin
  inherited Create;
  // Load Lua Lib if not already done
  if (not LuaLibLoaded) then
    LoadLuaLib;

  // Open Library
  LuaInstance := Lua_Open();
  luaopen_base(LuaInstance);

  fAutoRegister := AutoRegister;

  // Create Object List on initialization
  CallBackList := TList.Create;

  // if set then register published functions
  if (AutoRegister) then
    AutoRegisterFunctions(self);
end;

//
// Dispose Lua instance
//
destructor TLua.Destroy;
begin
  // Unregister all functions if previously autoregistered
  if (fAutoRegister) then
    UnregisterFunctions(Self);

  // dispose Object List on finalization
  CallBackList.Free;

  // Close instance
  Lua_Close(LuaInstance);
  inherited;
end;

//
// Wrapper for Lua File load and Execution
//
// @param       String  Filename        Lua Script file name
// @return      Integer
//
function TLua.DoFile(Filename: String): Integer;
begin
  Result := lual_dofile(LuaInstance, PAnsiChar(AnsiString(Filename)));
end;

//
// Register a new Lua Function and map it to the Objects method name
//
// @param       AnsiString      FuncName        Lua Function Name
// @param       AnsiString      MethodName      (optional) Objects Method name
//
procedure TLua.RegisterFunction(FuncName: AnsiString; MethodName: AnsiString = ''; Obj: TObject = NIL);
var
  CallBack: TCallBack; // Callback Object
begin
  // if method name not specified use Lua function name
  if (MethodName = '') then
    MethodName := FuncName;

  // if not object specified use this object
  if (Obj = NIL) then
    Obj := Self;

  // Add Callback Object to the Object Index
  CallBack := TCallBack.Create;
  CallBack.Routine.Data := Obj;
  CallBack.Routine.Code := Obj.MethodAddress(String(MethodName));
  CallBack.Exec := TProc(CallBack.Routine);
  CallbackList.Add(CallBack);

  // prepare Closure value (Method Name)
  lua_pushstring(LuaInstance, PAnsiChar(FuncName));

  // prepare Closure value (CallBack Object Pointer)
  lua_pushlightuserdata(LuaInstance, CallBack);

  // set new Lua function with Closure value
  lua_pushcclosure(LuaInstance, LuaCallBack, 1);
  lua_settable(LuaInstance, LUA_GLOBALSINDEX);
end;

//
// UnRegister all new Lua Function
//
// @param       TObject     Object      Object with prev registered lua functions
//
procedure TLua.UnregisterFunctions(Obj: TObject);
var
  I: Integer;
  CallBack: TCallBack;
begin
  // remove obj from object list
  for I := CallBackList.Count downto 1 do
  begin
    CallBack := CallBackList[I-1];
    if (assigned(CallBack)) and (CallBack.Routine.Data = Obj) then
    begin
      CallBack.Free;
      CallBackList.Items[I-1] := NIL;
      CallBackList.Delete(I-1);
    end;
  end;
end;

//
// Register all published methods as Lua Functions
//
procedure TLua.AutoRegisterFunctions(Obj: TObject);
type
  PPointer = ^Pointer;
  PMethodRec = ^TMethodRec;

  TMethodRec = packed record
    wSize: Word;
    pCode: Pointer;
    sName: ShortString;
  end;
var
  MethodTable: PAnsiChar;
  MethodRec: PMethodRec;
  wCount: Word;
  nMethod: Integer;
begin
  // Get a pointer to the class's published method table
  MethodTable := PAnsiChar(Pointer(PAnsiChar(Obj.ClassType) + vmtMethodTable)^);

  if (MethodTable <> Nil) then
  begin
    // Get the count of the methods in the table
    Move(MethodTable^, wCount, 2);

    // Position the MethodRec pointer at the first method in the table
    // (skip over the 2-byte method count)
    MethodRec := PMethodRec(MethodTable + 2);

    // Iterate through all the published methods of this class
    for nMethod := 0 to wCount - 1 do
    begin
      // Add the method name to the lua functions
      RegisterFunction(MethodRec.sName, MethodRec.sName, Obj);
      // Skip to the next method
      MethodRec := PMethodRec(PAnsiChar(MethodRec) + MethodRec.wSize);
    end;
  end;
end;


end.


lualib.pas

(******************************************************************************
* Original copyright for the lua source and headers:
*  1994-2004 Tecgraf, PUC-Rio.
*  www.lua.org.
*
* Copyright for the Delphi adaptation:
*  2005 Rolf Meyerhoff
*  www.matrix44.de
*
* Copyright for the Lua 5.1 adaptation:
*  2007 Marco Antonio Abreu
*  www.marcoabreu.eti.br
*
*  All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************)
unit LuaLib;

interface

const
  LUA_VERSION   = 'Lua 5.1';
  LUA_RELEASE   = 'Lua 5.1.2';
  LUA_COPYRIGHT = 'Copyright (C) 1994-2004 Tecgraf, PUC-Rio';
  LUA_AUTHORS   = 'R. Ierusalimschy, L. H. de Figueiredo & W. Celes';

  LUA_PASCAL_51_AUTHOR = 'Marco Antonio Abreu';
  LUA_PASCAL_51_COPYRIGHT = 'Copyright (C) 2007 Marco Antonio Abreu';

  (* mark for precompiled code (`<esc>Lua') *)
  LUA_SIGNATURE = #27'Lua';

  (* option for multiple returns in `lua_pcall' and `lua_call' 
近期因为需要,学习了一下LUA脚本语言,由于开发环境使用Delphi,所以学习侧重于DelphiLua脚本的使用。 虽然学习Delphi已经多年,但从未接触过Lua,通过网上搜索,这方面的资料也非常少,即便是找到了几篇帖子,不是泛泛而谈,就是语言表达模糊,难于理解。 为此笔者(游标)通过在网上的找到的一则(共四篇)学习笔记,经过一次次失败,算是初入Lua的大门。 原帖地址:http://www.cnitblog.com/xkz/category/8679.html【向作者表示感谢】 在此将自己根据帖子做的实例发给大家,避免大家再走弯路。 实例在原帖子的基础上,有所扩展,详细对于刚学Lua的新手有所帮助。至于高手,就一笑而过吧。 几点注意事项: 1、帖子中所说的lua, lualib, lauxlib, LuaUtils几个单元文件,不仅需要和工程文件在同一文件夹下,而且要添加到工程中,并在工程中引用。同时,引用的位置最好在头部的Uses中,否则那个关于累加的例子会出错。 2、Lua.dll需要放在工程中。 3、原帖中省略了很多代码(或者说是表达上省略了),给初学者的理解造成了很多误区。在我的实例中都给出了完整代码。 最后对CSDN上发源码的朋友说一句,发源码希望不要糊弄了事,注释多一些,说明详细些,重复的、完全是糊弄人的源码少发些。大家时间都很宝贵,下载积分也来之不易。浪费在无意义的下载上,实在心疼。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值