文章目录
-
- [5.2 -- Coroutine Manipulation](#5.2 – Coroutine Manipulation)
-
- [`coroutine.create (f)`](#
coroutine.create (f)
) - [`coroutine.resume (co [, val1, ···])`](#
coroutine.resume (co [, val1, ···])
) - [`coroutine.running ()`](#
coroutine.running ()
) - [`coroutine.status (co)`](#
coroutine.status (co)
) - [`coroutine.wrap (f)`](#
coroutine.wrap (f)
) - [`coroutine.yield (···)`](#
coroutine.yield (···)
)
- [`coroutine.create (f)`](#
- [5.3 -- Modules](#5.3 – Modules)
-
- [`module (name [, ···])`](#
module (name [, ···])
) - [`require (modname)`](#
require (modname)
) - `package.loaded`
- `package.loaders`
- `package.preload`
- `package.path`
- `package.cpath`
- [`package.loadlib (libname, funcname)`](#
package.loadlib (libname, funcname)
) -
- [例子:package.loadlib 的使用](#例子:package.loadlib 的使用)
- [`package.seeall (module)`](#
package.seeall (module)
)
- [`module (name [, ···])`](#
- [5.4 -- String Manipulation](#5.4 – String Manipulation)
-
- [`string.byte (s [, i [, j]])`](#
string.byte (s [, i [, j]])
) - [`string.char (···)`](#
string.char (···)
) -
- [例子:string.byte 和 string.char 的使用](#例子:string.byte 和 string.char 的使用)
- [`string.format (formatstring, ···)`](#
string.format (formatstring, ···)
) -
- [例子:string.format 的使用](#例子:string.format 的使用)
- [`string.len (s)`](#
string.len (s)
) - [`string.lower (s)`](#
string.lower (s)
) - [`string.upper (s)`](#
string.upper (s)
) - [`string.rep (s, n)`](#
string.rep (s, n)
) - [`string.reverse (s)`](#
string.reverse (s)
) - [`string.sub (s, i [, j])`](#
string.sub (s, i [, j])
) - [`string.dump (function)`](#
string.dump (function)
)
- [`string.byte (s [, i [, j]])`](#
5.2 -- Coroutine Manipulation
The operations related to coroutines comprise a sub-library of the basic library and come inside the table coroutine
. See §2.11 for a general description of coroutines.
coroutine.create (f)
Creates a new coroutine, with body f
. f
must be a Lua function. Returns this new coroutine, an object with type "thread"
.
coroutine.resume (co [, val1, ···])
Starts or continues the execution of coroutine co
. The first time you resume a coroutine, it starts running its body. The values val1
, ··· are passed as the arguments to the body function. If the coroutine has yielded, resume
restarts it; the values val1
, ··· are passed as the results from the yield.
If the coroutine runs without any errors, resume
returns true plus any values passed to yield
(if the coroutine yields) or any values returned by the body function (if the coroutine terminates). If there is any error, resume
returns false plus the error message.
coroutine.running ()
Returns the running coroutine, or nil when called by the main thread.
coroutine.status (co)
Returns the status of coroutine co
, as a string:
"running"
, if the coroutine is running (that is, it called status
);
"suspended"
, if the coroutine is suspended in a call to yield
, or if it has not started running yet;
"normal"
if the coroutine is active but not running (that is, it has resumed another coroutine);
and "dead"
if the coroutine has finished its body function, or if it has stopped with an error.
例子:协程的状态
lua
-- 创建一个协程
local co
co = coroutine.create(function()
print("协程1开始执行")
-- 检查协程状态,应该是running
print("协程1状态: " .. coroutine.status(co)) -- "running"
local co2 = coroutine.create(function()
print("协程2开始执行")
print("协程2里的协程1状态: " .. coroutine.status(co)) -- "normal"
print("协程2执行结束")
end)
-- 启动协程2
coroutine.resume(co2)
coroutine.yield() -- 暂停协程
print("协程1恢复执行")
end)
-- 初始状态:协程被创建但未执行,所以状态是"suspended"
print("协程1初始状态: " .. coroutine.status(co)) -- "suspended"
-- 启动协程
coroutine.resume(co)
-- 在协程内部调用status,应该输出"running"
-- 输出会在协程内部看到,表明此时协程正在执行
print("协程1执行后,状态: " .. coroutine.status(co)) -- "suspended"(外部查看状态,仍然是suspended)
-- 恢复协程
coroutine.resume(co)
-- 最后,协程结束,状态变为"dead"
print("协程1结束后的状态: " .. coroutine.status(co)) -- "dead"
输出
协程1初始状态: suspended
协程1开始执行
协程1状态: running
协程2开始执行
协程2里的协程1状态: normal
协程2执行结束
协程1执行后,状态: suspended
协程1恢复执行
协程1结束后的状态: dead
coroutine.wrap (f)
Creates a new coroutine, with body f
. f
must be a Lua function. Returns a function that resumes the coroutine each time it is called. Any arguments passed to the function behave as the extra arguments to resume
. Returns the same values returned by resume
, except the first boolean. In case of error, propagates the error.
coroutine.yield (···)
Suspends the execution of the calling coroutine. The coroutine cannot be running a C function, a metamethod, or an iterator. Any arguments to yield
are passed as extra results to resume
.
协程的例子见这篇文章
5.3 -- Modules
The package library provides basic facilities for loading and building modules in Lua. It exports two of its functions directly in the global environment: require
and module
. Everything else is exported in a table package
.
module (name [, ···])
忽略,基本不使用
require (modname)
Loads the given module. The function starts by looking into the package.loaded
table to determine whether modname
is already loaded. If it is, then require
returns the value stored at package.loaded[modname]
. Otherwise, it tries to find a loader for the module.
To find a loader, require
is guided by the package.loaders
array. By changing this array, we can change how require
looks for a module. The following explanation is based on the default configuration for package.loaders
.【见package.loaders中的说明】
First require
queries package.preload[modname]
. If it has a value, this value (which should be a function) is the loader. Otherwise require
searches for a Lua loader using the path stored in package.path
. If that also fails, it searches for a C loader using the path stored in package.cpath
. If that also fails, it tries an all-in-one loader (see package.loaders
).
Once a loader is found, require
calls the loader with a single argument, modname
. If the loader returns any value, require
assigns the returned value to package.loaded[modname]
. If the loader returns no value and has not assigned any value to package.loaded[modname]
, then require
assigns true to this entry. In any case, require
returns the final value of package.loaded[modname]
.
If there is any error loading or running the module, or if it cannot find any loader for the module, then require
signals an error.
package.loaded
A table used by require
to control which modules are already loaded. When you require a module modname
and package.loaded[modname]
is not false, require
simply returns the value stored there.
package.loaders
A table used by require
to control how to load modules.
Each entry in this table is a searcher function. When looking for a module, require
calls each of these searchers in ascending order, with the module name (the argument given to require
) as its sole parameter. The function can return another function (the module loader ) or a string explaining why it did not find that module (or nil if it has nothing to say). Lua initializes this table with four functions.
The first searcher simply looks for a loader in the package.preload
table.
The second searcher looks for a loader as a Lua library, using the path stored at package.path
. A path is a sequence of templates separated by semicolons. For each template, the searcher will change each interrogation mark in the template by filename
, which is the module name with each dot replaced by a "directory separator" (such as "/
" in Unix); then it will try to open the resulting file name. So, for instance, if the Lua path is the string
"./?.lua;./?.lc;/usr/local/?/init.lua"
the search for a Lua file for module foo
will try to open the files ./foo.lua
, ./foo.lc
, and /usr/local/foo/init.lua
, in that order.
The third searcher looks for a loader as a C library, using the path given by the variable package.cpath
. For instance, if the C path is the string
"./?.so;./?.dll;/usr/local/?/init.so"
the searcher for module foo
will try to open the files ./foo.so
, ./foo.dll
, and /usr/local/foo/init.so
, in that order. Once it finds a C library, this searcher first uses a dynamic link facility to link the application with the library. Then it tries to find a C function inside the library to be used as the loader. The name of this C function is the string "luaopen_
" concatenated with a copy of the module name where each dot is replaced by an underscore. Moreover, if the module name has a hyphen, its prefix up to (and including) the first hyphen is removed. For instance, if the module name is a.v1-b.c
, the function name will be luaopen_b_c
.
The fourth searcher tries an all-in-one loader . It searches the C path for a library for the root name of the given module. For instance, when requiring a.b.c
, it will search for a C library for a
. If found, it looks into it for an open function for the submodule; in our example, that would be luaopen_a_b_c
. With this facility, a package can pack several C submodules into one single library, with each submodule keeping its original open function.
package.preload
A table to store loaders for specific modules (see require
).
package.path
The path used by require
to search for a Lua loader.
At start-up, Lua initializes this variable with the value of the environment variable LUA_PATH
or with a default path defined in luaconf.h
, if the environment variable is not defined. Any ";;
" in the value of the environment variable is replaced by the default path
package.cpath
The path used by require
to search for a C loader.
Lua initializes the C path package.cpath
in the same way it initializes the Lua path package.path
, using the environment variable LUA_CPATH
or a default path defined in luaconf.h
.
package.loadlib (libname, funcname)
Dynamically links the host program with the C library libname
. Inside this library, looks for a function funcname
and returns this function as a C function. (So, funcname
must follow the protocol (see lua_CFunction
)).
This is a low-level function. It completely bypasses the package and module system. Unlike require
, it does not perform any path searching and does not automatically adds extensions. libname
must be the complete file name of the C library, including if necessary a path and extension. funcname
must be the exact name exported by the C library (which may depend on the C compiler and linker used).
This function is not supported by ANSI C. As such, it is only available on some platforms (Windows, Linux, Mac OS X, Solaris, BSD, plus other Unix systems that support the dlfcn
standard).
例子:package.loadlib 的使用
mylib.c
c
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
// C 函数:加法
int add(lua_State *L) {
// 从栈中获取两个参数
double a = luaL_checknumber(L, 1);
double b = luaL_checknumber(L, 2);
// 将结果推送到 Lua 栈上
lua_pushnumber(L, a + b);
return 1; // 返回一个结果
}
// 导出函数
int luaopen_mylib(lua_State *L) {
lua_register(L, "add", add); // 注册 add 函数
return 0;
}
编译
gcc -o mylib.so -shared mylib.c -fPIC -I/usr/local/include/luajit-2.1 -lluajit-5.1
lua代码
lua
-- 使用 package.loadlib 加载共享库
local lib = package.loadlib("./mylib.so", "luaopen_mylib")
-- 加载库后,调用返回的函数
lib() -- 这会注册 C 库中的 "add" 函数到 Lua 环境
-- 调用 "add" 函数,传递两个数字
local result = add(10, 20)
print("结果:", result) -- 输出: 结果: 30
package.seeall (module)
忽略,基本不使用
5.4 -- String Manipulation
This library provides generic functions for string manipulation, such as finding and extracting substrings, and pattern matching. When indexing a string in Lua, the first character is at position 1 (not at 0, as in C). Indices are allowed to be negative and are interpreted as indexing backwards, from the end of the string. Thus, the last character is at position -1, and so on.
The string library provides all its functions inside the table string
. It also sets a metatable for strings where the __index
field points to the string
table. Therefore, you can use the string functions in object-oriented style. For instance, string.byte(s, i)
can be written as s:byte(i)
.
The string library assumes one-byte character encodings.
string.byte (s [, i [, j]])
Returns the internal numerical codes of the characters s[i]
, s[i+1]
, ···, s[j]
. The default value for i
is 1; the default value for j
is i
.
Note that numerical codes are not necessarily portable across platforms.
string.char (···)
Receives zero or more integers. Returns a string with length equal to the number of arguments, in which each character has the internal numerical code equal to its corresponding argument.
Note that numerical codes are not necessarily portable across platforms.
例子:string.byte 和 string.char 的使用
lua
local bytes = { string.byte("hello", 1, #("hello")) }
for i, b in ipairs(bytes) do
print(b) -- 输出 'h', 'e', 'l', 'l', 'o' 的字节值 104 101 108 108 111
end
print(string.char(104, 101, 108, 108, 111)) -- 输出 hello
string.format (formatstring, ···)
Returns a formatted version of its variable number of arguments following the description given in its first argument (which must be a string). The format string follows the same rules as the printf
family of standard C functions. The only differences are that the options/modifiers *
, l
, L
, n
, p
, and h
are not supported and that there is an extra option, q
. The q
option formats a string in a form suitable to be safely read back by the Lua interpreter: the string is written between double quotes, and all double quotes, newlines, embedded zeros, and backslashes in the string are correctly escaped when written. For instance, the call
string.format('%q', 'a string with "quotes" and \n new line')
will produce the string:
"a string with \"quotes\" and \
new line"
The options c
, d
, E
, e
, f
, g
, G
, i
, o
, u
, X
, and x
all expect a number as argument, whereas q
and s
expect a string.
This function does not accept string values containing embedded zeros, except as arguments to the q
option.
%c - 接受一个数字,并将其转化为ASCII码表中对应的字符
%d, %i - 接受一个数字并将其转化为有符号的整数格式
%o - 接受一个数字并将其转化为八进制数格式
%u - 接受一个数字并将其转化为无符号整数格式
%x - 接受一个数字并将其转化为十六进制数格式,使用小写字母
%X - 接受一个数字并将其转化为十六进制数格式,使用大写字母
%e - 接受一个数字并将其转化为科学记数法格式,使用小写字母e
%E - 接受一个数字并将其转化为科学记数法格式,使用大写字母E
%f - 接受一个数字并将其转化为浮点数格式
%g(%G) - 接受一个数字并将其转化为%e(%E,对应%G)及%f中较短的一种格式
%q - 接受一个字符串并将其转化为可安全被Lua编译器读入的格式
%s - 接受一个字符串并按照给定的参数格式化该字符串
为进一步细化格式, 可以在%号后添加参数.参数将以如下的顺序读入:
(1) 符号:一个+号表示其后的数字转义符将让正数显示正号.默认情况下只有负数显示符号.
(2) 占位符: 一个0,在后面指定了字串宽度时占位用.不填时的默认占位符是空格.
(3) 对齐标识: 在指定了字串宽度时,默认为右对齐,增加-号可以改为左对齐.
(4) 宽度数值
(5) 小数位数/字串裁切:在宽度数值后增加的小数部分n,若后接f(浮点数转义符,如%6.3f)则设定该浮点数的小数只保留n位,若后接s(字符串转义符,如%5.3s)则设定该字符串只显示前n位.
在这些参数的后面则是上述所列的转义码类型(c, d, i, f, ...).
例子:string.format 的使用
lua
print(string.format("%%c: %c", 83)) -- %c: S
print(string.format("%+d", 17.0)) -- +17
print(string.format("%05d", 17)) -- 00017
print(string.format("%o", 17)) -- 21
print(string.format("%u", 3.14)) -- 3
print(string.format("%x", 13)) -- d
print(string.format("%X", 13)) -- D
print(string.format("%e", 1000)) -- 1.000000e+03
print(string.format("%E", 1000)) -- 1.000000E+03
print(string.format("%6.3f", 13)) -- 13.000
print(string.format("%s", "monkey")) -- monkey
print(string.format("%10s", "monkey")) -- monkey
print(string.format("%5.3s", "monkey")) -- mon
string.len (s)
Receives a string and returns its length. The empty string ""
has length 0. Embedded zeros are counted, so "a\000bc\000"
has length 5.
string.lower (s)
Receives a string and returns a copy of this string with all uppercase letters changed to lowercase. All other characters are left unchanged. The definition of what an uppercase letter is depends on the current locale.
string.upper (s)
Receives a string and returns a copy of this string with all lowercase letters changed to uppercase. All other characters are left unchanged. The definition of what a lowercase letter is depends on the current locale.
string.rep (s, n)
Returns a string that is the concatenation of n
copies of the string s
.
string.reverse (s)
Returns a string that is the string s
reversed.
string.sub (s, i [, j])
Returns the substring of s
that starts at i
and continues until j
; i
and j
can be negative. If j
is absent, then it is assumed to be equal to -1 (which is the same as the string length). In particular, the call string.sub(s,1,j)
returns a prefix of s
with length j
, and string.sub(s, -i)
returns a suffix of s
with length i
.
string.dump (function)
Returns a string containing a binary representation of the given function, so that a later loadstring
on this string returns a copy of the function. function
must be a Lua function without upvalues.