基础库(LAScript basic library)

 

一、基础库-系统变量

_G

全局名字空间,指向基础库自身.
基础库的所有成员都可以加上_G前缀,包括_G自身也可以写为_G._G;
一个有趣的测试:

win.messageBox(type(_G._G._G._G._G._G._G._G._G._G._G._G));

--你可以连接写任意多个_G前缀,_G总是指向自已

_VERSION

返回模拟精灵版本号

有时候我们可能需要在运行以前检测模拟精灵的版本:
if _VERSION<2005710 then
    win.messageBox("本程序要求模拟精灵2005 v710以上版本");
    return false;
end;

您还可以用更简洁的写法:

assert(_VERSION>=2005710,"本程序要求模拟精灵2005 v710以上版本".._VERSION);

_LASPATH

返回脚本文件路径(如果是fap程序,则返回_FAPPATH )。
如果是尚未保存的文件返回模拟精灵主程序路径。

_LASDIR

返回脚本文件所在目录(如果是fap程序,则返回fap文件所在目录)。
如果是尚未保存的文件返回模拟精灵主程序所在目录。

_FAPPATH

返回fap文件所在路径。
如果是尚未保存的文件返回模拟精灵主程序路径。

_TRUE

等于1,在调用API函数时表示非零值

_FALSE

等于0,在调用API函数时表示零值

_NULL

等于0,通常用在win库函数中或API函数中表示无效的句柄或无效的指针。

二、基础库-常用函数

1、流程控制、内存管理

nStop()
如果用户发送了全部停止指令,nStop()返回false,如果程序正在运行用户也没有按停止nStop()返回true;

stop()
发送全部停止指令;

delay(s)
延时,s指定延时值,以毫秒为单位;

这避免被目标程序被发现是使用模拟程序在模拟人工操作,可以使用随机的延时。
下面是一个例子:
delay( math.random( 1000, 6000) ); --延时参数为1000毫秒到6000毫秒之间的随机数

sleep(s)
休眠,s指定延时值,以毫秒为单位;
用sleep函数延时更节省资源。但是fap程序休眠时不会响应操作。collectgarbage()
执行垃圾收集,清理内存;

2、名字空间、环境表

namespace("",[...]);
创建名字空间,可添任意多个可选参数,如果参数是函数则将创建的名字空间作为参数调用这个函数,如果参数是table表则继承这个表的所有成员。

import("")
导入外部名字空间、名字空间可以在一个las脚本库或者一个dll插件库中。getfenv (f)
返回当前环境表(默认名字空间),f可以是函数也可以是数字,默认1指当前函数,0则返回全局环境;setfenv (f, tab)
为指定级别的函数域设定环境表,f可以是函数也可以是数字,如果f为0改变当前线程的全局环境.
第十个参数是一个tab类型的对象( 注意不是字符串,这与namespace函数不同)

3、类据类型转换

tonumber (e [, base])
转换为数值(失败返回nil).base指定进制,当base大于10时,忽略大小写的'A'将转换为10,'B'将转换为11,'Z'将转换为35,取默认值10时,返回值可能含有小数.

tostring (e)
转换为字符串

type (v)
返回参数的类型,返回值为字符串:"nil" , "number", "string", "boolean", "table", "function","thread", "userdata".

4、调试

print (e1, e2, ...)
在控制台输出参数值.支持任意类型任意个数的变量。
必须首先用win.consoleOpen()打开控制台窗口

assert (v [, message])
断言函数,检测参数v的值,当v为nil或false时则显示出错信息;message为可选的出错信息,默认值为“assertion failed!”

error (message [, level])
终止最后一个受保护的函数的运行,返回message,而该函数的出错信息不会返回.
参数level指定了出错信息所反映的位置,取默认值1时,指向调用出错的函数的位置,取2时,指向引起error的函数被调用的位置,依此类推.pcall (f, arg1, arg2, ...)
保护模式调用函数f,捕捉错误并返回状态码.返回的第一个值为该函数的状态码(布尔型),无错时继续返回函数的返回值,出错时返回false及出错信息.

xpcall (f, err)
类似于pcall,但允许指定错误处理handler.


5、table、字典、数组

tmeta = getmetatable (tab)
返回对象的元表(metatable)。
如果元表(metatable)中存在__metatable键值,当返回__metatable的值。
使用__metatable可以保护元表,禁止用户访问元表中的成员。

setmetatable (table, metatable)
对指定table设置metatable。
如果元表(metatable)中存在__metatable键值,setmetatable会失败。
使用__metatable可以保护元表,禁止用户修改元表。

pairs (t)
table字典迭代器,使用方法请参考:遍历table列表中的全部元素

ipairs (t)
table数组迭代器,使用方法请参考:遍历table列表中的数组元素

k,v = next (tab [, key])

返回table的下一个元素,当key为nil时(或省略),返回第一个元素,
为table的最后一个下标或空table的nil时,返回nil.

win.consoleOpen()
tab = {"字符串", 123,"字符串2",23,56,78,99,123,0,test=123};--tab.test不是数组元素
 
--如果第二个参数不指定当前键,返回第一个元素的键和值
k,v = next(tab);
print(k,v);
 
--如果第二个参数指定当前键,返回下一个元素的键和值
k,v = next(tab,k)
print(k,v);
 
--如果当前键为最后一个键,返回nil
k,v = next(tab,"test")
print(k,v);

如何在「fap模拟程序」中用next函数循环遍历一个表又重新开始?

「fap模拟程序」本就会有一个「周而复始」的循环,所以我们通常不用for循环来遍历一个表。
如果我们要在fap模拟程序的循环过程中遍历一个表,用next函数就很方便。

首先在最前面放一个脚本区块,命名为init这样这个区块就只会执行一次。
在init区块中创建或加载table。

local str = string.load("c:\\code.txt","rt");--读取文本文件
_tab = table.loadList(str ,"\n");--生成table字典

--string.split( str,"\n"); --普通的文本分行用这句拆分成有顺序的数组

然后在其他区块就可以用next函数周而复始的循环遍历table列表:

_k,_v = next(_tab,_k); --读取table的下一个元素
if(not k) then --如果到了最后面
     _k,_v = next(_tab); --再重新开始,这就是上面说的「周而复始」
end;

在后面的程序中,就可以直接使用当前位置的 _k , _v 变量了。

m = ape:getModule("发送文本的模拟区块名字");
m:setStringList( { _v } );

 

unpack (list)
返回给定table数组的所有元素.

select (index, ...)
如果index是一个数值,返回第index+1个参数,如果是"#"字符,返回参数总数。

6、加载脚本

dofile (filename)
打开指定文件并作为语句块执行,无参数时执行stdin的内容,不能在保护模式中使用.
实际上是一个辅助的函数,真正完成功能的函数是loadfile;

loadfile (filename)
载入一个文件但不执行,不发生错误时,返回一个函数,否则返回nil和出错信息.返回的函数的环境为全局环境.

loadfile编译代码成中间码并且返回编译后的chunk作为一个函数,而不执行代码;
f = loadfile("test.las");--返回一个函数对象,并不会立即执行
f(); --这样才会执行脚本
 
--dofile函数实际上就是执行上面两句代码的功能

loadfile不会抛出错误而仅仅在第二个返回值中返回错误信息.
如果我们需要抛出错误,可以使用assert断言函数,loadfile返回值的数目与规则正好符合assert的需要。
local f = assert(loadfile("c:\\test.las"));

--如果loadfile遇到错误,返回值成为assert的参数 assert(nil,"loadfile返回的错误信息") 抛出一个错误.
--如果loadfile成功,返回值成为assert的参数 assert(f); f是一个函数对象,断言成功,assert再返回f


您可能觉得dofile比较方便,他读入文件编译并且执行.然而loadfile更加灵活.在发生错误的情况下,loadfile返回nil和错误信息, 这样我们就可以自定义错误处理.另外,如果我们运行一个文件多次的话, loadfile只需要编译一次,但可多次运行. dofile却每次都要编译.



loadstring (string [, chunkname])
载入字符串但不执行,与loadfile (filename)相近.chunkname用于出错信息和debug信息.

loadstring与loadfile相似,只不过它不是从文件里读入,而是从一个字符串中读入语句块(chunk,这里可以看作一个匿名函数).例如:
f = loadstring("i = 1")
f();
 
--上面的代码可以合并为一句,如下:
loadstring("i = 1")();
 
--还可以在loadstring返回值以前用assert断言函数捕获错误
assert( loadstring("i = ") )();


loadstring可以访问全局变量
win.consoleOpen();
 
f = loadstring("i = i + 1"); --loadstring可以访问全局变量
--[[
loadstring实际上生成一个匿名函数 上面的代码等效于下面的代码:
f = function i = i + 1 end;

]]

i = 110;
 
f();
print(i);    --> 显示1
 
f();
print(i);    --> 显示2 loadstring返回的函数和普通函数一样,可以多次被调用

loadstring总是在全局环境中编译他的串.
local i = 0
f = loadstring("i = i + 1") --f使用全局变量
f2 = function () i = i + 1 end --f2使用局部变量i,

loadstring就是一个匿名函数,可以通过return语句返回值.
local func = loadstring( " return '这是一个返回值' " )
str = func();

win.messageBox(str);

loadstring与loadfile一样都不会抛出错误,如果发生错误他们将返回nil加上错误信息:
print(loadstring("i i")); --正确的应当是 i = i,少写一个等号制造一个语法错误
-->显示两个返回值 nil, [string "i i"]:1: `=' expected near `i'

loadstring和loadfile只是编译代码并不会执行代码.代码中包含的函数或变量在编译时并不会创建.
las =[[
function func (str)
    win.consoleOpen()
    print(str)
end
]]
 
f = loadstring(las); --并不会定义函数对象func
func(); --肯定出错
 
f(); --执行时才会定义新的函数func
func("成功了");
注意:通常使用loadstring加载一个字串没什么意义,例如:
f = loadstring("i = i + 1")
大概与f = function () i = i + 1 end 等价,而后者更快. 所以不要滥用loadstring

loadstring通常用于运行程序外部的代码,比如运行用户自定义的代码.从网络下载的代码或加密的代码等.
xmlString = web.getURL("http://www.yhhe.net/ape/lib/ape/testweb.xml");
 
xmlTable = {};
xmlTable = table.load(xmlString);
--从XML字符串创建表,table.load(str)自动分析str是文件路径还是XML字符串
lasString = xmlTable["LAScript"]; --调用网页上的变量
 
fun = loadstring( lasString ) ; --调用网页上的变量;
fun(); --调用网页上的脚本

load (getlas [, chunkname])
调用getlas函数返回脚本代码,直到getlas返回nil,然后编译代码并返回一个函数对象

也就是说load会不断的执行getlas,一直到getlas返回nil值.
如果getlas从不返回nil值,很明显这会造成是一个死循环.

local tag =0;
function getlas()  
    tag = tag +1;
    if(tag<10)then
        return " print 'ok' ";
    end;
end;

--不断的调用getlas,直到getlas返回nil空值(或者没有返回值)
f = load(getlas,"name");
 
win.consoleOpen();
f();

7、其他函数

rawequal (v1, v2)
比较两个参数.

rawget (tab, index)
取得tab[index]的值,index不能为nil.

rawset (tab, index, value)
对tab[index]赋值.