链表实现
t = {1, 2, 3, 4, 5, 6}n = table.getn(t); --表的长度list = null;for i = 1, n dolist = {val = t[i], next = list}end-- 自定义ipairs接口function ipairs_iter(t, node)if node == nil then return t;else return node.nextendendfunction ipairs_list(t)return ipairs_iter, t, nilend-- 遍历for node in ipairs_list(list) doprint(node.val)end-- 删除链表中的某个function delnode(list, val)for node in ipairs_list(list) dolocal preNode = node; -- 上一个节点local curNode = node.next; -- 当前节点if curNode ~= nil and curNode.val == val thenlocal nextNode = curNode.next; -- 下一个节点preNode.next = nextNode;curNode = nil;endendenddelnode(list, 3); -- 删除list中值为3的元素-- 遍历for node in ipairs_list(list) doprint(node.val)end
lua元表
a = {1, 2, 3}b = {2, 3, 4}--定义元表mt = {}--定义元表相加方法mt.__add = function(a, b)local len = table.getn(a);local res = {}for i = 1, len dores[i] = a[i] + b[i];endreturn res;end--定义元表相连方法mt.__concat = function(a, b)local len = table.getn(a);local res = {};for i = 1, len dores[i] = a[i] .. b[i]endreturn res;end--定义等于方法mt.__eq = function(a, b)local len = table.getn(a);local res = false;for i = 1, len doif a[i] ~= b[i] thenres = true;break;endendif res == false thenreturn trueelsereturn false;endend--设置a,b的元表setmetatable(a, mt);setmetatable(b, mt);c = a + b;for k,v in ipairs(c) doprint(v); -- 3 5 7endd = a .. b;local len = table.getn(d);for i = 1, len doprint(d[i]); --12 23 34end-------------------------------index表示当在mywindow没有找到元素时,会在父表中寻找Window = {x = 0, y = 0, width = 100, height = 200}Window.__index = function(t, key)return Window[key];end--当去修改元表中的值时,用的是newindexWindow.__newindex = function(t, k, v)Window[k] = v;endmyWindow = {};setmetatable(myWindow, Window);printf(myWindow.width); --100 没有找到会在父表中寻找printf(rawget(myWindow, width)); --nil 只在自己的表中查询myWindow.test = 1000; --设置在了父元素上printf(myWindow.test); --1000printf(rawget(myWindow, test)); --nil-----------------------------定义字符串方法Window.__tostring = function(t)local len = table.getn(t);local s = "";for i = 1, len dos = s .. ",";endend
lua环境表
--防止在函数内部定义全局变量-- 教程:https://www.bilibili.com/video/BV1Zz411i7QW?p=12local declaredNames = {}local mt = {__newindex = function(table, name, value)--先检查新的名字是否已经声明过,如果存在,这直接通过rawset函数设置即可if not declaredNames[name] then--再检查本次操作是否是再主程序或者C代码中完成的,如果是,就继续设置,否在报错local w = debug.getinfo(2, "S").whatif w ~= "main" and w ~= "C" thenprint(w)error("attempt to write to undeclared variable" .. name);end--在实际设置之前,更新一下declaredNames表,下次再设置时就无需检查了declaredNames[name] = true;endprint("Setting " .. name .. " to " .. value);rawset(table, name, value);end,__index = function(_,name)if not declaredNames[name] thenerror("attempt to read undeclared variable " .. name)elsereturn rawget(_,name)endend}setmetatable(_G,mt);a = 11local kk = aa --报错 不能将全局变量赋值给局部变量
lua package包
for k,v in pairs(package.loaded) doprint(k,v)endprint("-----------------------");for k,v in pairs(package.preload) doprint(k,v)end--print(package.path); --寻找包路径require "mathlib" --查找mathlib文件--require执行流程--1.首先在package.loaded查找modelname--2.在packagepreload查找modelname,如果preload存在,那就把它作为loader,调用loader[L]--3.根据package.path查找lua文件--4.根据package.cpath查找c库,并调用相应名字的接口
—mathilb.lua文件
local P = {} --未加local则会被调用的文件给覆盖了mathlib = Pfunction P.add(a, b)return a + bendfunction P.sub(a, b)return a-bendfunction P.sum(...)local _sum = 0for k = 1, arg.n do_sum = P.add(_sum, arg[k])endreturn _sum;endreturn P;
另一种写法
-----------------------local libname = ...local P = {}mathlib = P; --另一种 _G[libname] = P;setmetatable(P, {__index = _G});setfenv(1, P);--module(...) 上面的功能lua内部封装好了module(...)-----------------------function add(a, b)return a+b;endfunction sub(a,b)return a-b;endfunction sum(...)local _sum = 0;for k = 1, arg.n do_sum = add(_sum, arg[k])endreturn _sum;end------------return P;------------
—test.lua文件
mathlib = {x = 100}print(mathlib.x)local lib = require "mathlib"print(lib.sum(1,2,3,4,5,6,7,8))print(mathlib.x)--100 36 100(如果被调用的文件mathlib不是local变量时,则为nil)
面向对象设计
CPeople = {name = "default name", age = 10, sex = "fale"}function CPeople.new(p, o)o = o or {}setmetatable(o, p)p.__index = p;return o;endfunction CPeople.Walk()print("walk");endfunction CPeople.Say()print("Say");endfunction CPeople.Print(p)p = p or CPeople;print(p.name, p.age);end--子类实现 并继承父类CMale = {}function CMale:new(o)o = o or {}setmetatable(o, self);self.__index = self;setmetatable(self, CPeople); --继承CPeople类的属性和方法CPeople.__index = CPeople;endlocal p1 = CPeople.new(CPeople, {name = "zhanshang", age = 10});p1.Walk(); --walkp1.Print(); --default name 10p1.Print(p1); --zhanshang 10local p2 = CMale:new();p2:Walk(); --walk 若自己没有定义,则来自父类的方法/*-----------------------------------------------------------------------可以隐藏掉第一个参数function CPeople:new( o)o = o or {}setmetatable(o, self)self.__index = self;return o;endfunction CPeople:Walk()print("walk");endfunction CPeople:Say()print("Say");endfunction CPeople:Print()print(self.name, self.age);end--隐藏掉的第一个参数调用local p1 = CPeople:new({name = "zhanshang", age = 10});p1:Walk();p1:Print();--walk--zhanshang 10---------------------------------------------------------------------*/
弱表
--手动回收函数
--collectgarbage()
--weak table定义
--__mode字段可以取以下三个值:k, v, kv;
--k表示table.key 是weka的,也就是table的keys能够被自动gc
--v表示table.value是weak的,也就是table的values能被自动gc
--kv就是二者的组合,任何情况下,只要key和value中的一个被gc,
--那么这个key-value pair就从表中移除了
local defaults = {}
setmetatable(defaults, {_mode = "k"})
local mt = {__index = function(t) return defaults[t] end}
function setDefault(t, d)
defauls[t] = d;
setmetatable(t, mt);
end
t = {};
setDefault(t, 10);
print(t[x]);
c调用lua
main.c
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include <srring.h>
void main()
{
lua_State *L = lua_open();
luaopen_base(L);
lua_dofile(L, "../test.lua"); // lua文件
int d;
scanf("%d", d);
lua_close(L);
}
test.lua
a = 1;
print(a);
访问lua全局变量
//1.将变量入栈 lua_getglobal
//2.将堆栈对应的元素转换成相应的类型 lua_toxxx
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include <srring.h>
int getval(lua_State *L, const char * name)
{
int val = 0;
lua_getglobal(L, name); // 访问lua的全局变量a
if(1 == lua_isnumber(L, -1)) // -1表示栈顶
{// 检查栈顶是否为数字
val = lua_tonumber(L, -1); // 获取栈顶值
lua_pop(L, -1); // 出栈 将栈恢复到原来的样子
}
return val
}
// 从表中获取键的值
int getfield(lua_State *L, const char *table, const char *key)
{
int val = 0;
lua_getglobal(L, table); // window表入栈
lua_pushstring(L, key); // k入栈
lua_gettable(L, -2); // k出栈,将k所对应的val入栈
val = lua_tonumber(L, -1); // 获取width键的值
lua_pop(L, -1); // width键的值出栈
lua_pop(L, -1); // table表出栈
return val;
}
void main()
{
lua_State *L = lua_open();
luaopen_base(L);
int width, height;
lua_dofile(L, "../test.lua"); // 加载并运行指定的文件
width = getval(L, "width");
height = getval(L, "height");
width = getfield(L, "window", "width"); // 从window表中获取width键的值
height = getfield(L, "window", "height"); // 从window表中获取height键的值
int d;
scanf("%d", d);
lua_close(L);
}
/**********第二种情况***********
test.lua文件
width = 10
height = 20
print(a)
**********************/
/*********第二种情况************
test.lua文件
window = {width = 10, height = 20}
print(a)
**********************/
调用lua函数
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include <string.h>
}
// 获取lua函数的返回值,函数返回值只有1个时
int getval(lua_State *L, const char *funname)
{
int val = 0;
lua_getglobal(L, funname); // getwidth函数进栈
lua_pcall(L, 0, 1, 0); // lua指针,参数,返回值,错误状态 /* 先将函数出栈,然后返回值入栈 此时栈内只有函数的返回值*/
val = lua_tonumber(L, -1); // 获取栈内的值并转为数字类型
lua_pop(L, -1); // 栈内的最后一个内容出栈,清空栈
return val;
}
// 获取lua函数的返回值,函数返回值有2个时
int* getval(lua_State *L, const char *funname)
{
int val[2] = {0};
lua_getglobal(L, funname); // getwidth函数进栈
lua_pcall(L, 0, 2, 0); // lua指针,参数,返回值,错误状态 /* 先将函数出栈,然后返回值入栈 此时栈内只有函数的返回值*/
val[0] = lua_tonumber(L, -2); // 获取栈内的值并转为数字类型
val[1] = lua_tonumber(L, -1);
lua_pop(L, -1); // 栈内的最后一个内容出栈,清空栈
lua_pop(L, -1);
return val;
}
void main()
{
lua_State *L = lua_open();
luaopen_base(L);
int width, height;
lua_dofile(L, "D:/Visual_Studio_Code/test/test/test.lua"); // 加载并运行指定的文件
width = getval("getwidth")[0];
height = getval("getheight")[1];
// 向lua函数传参
int sum = 0;
lua_getglobal(L, "add");
lua_pushnumber(L, 100); // 传递第一个参数
lua_pushnumber(L, 200); // 传递第二个参数
lua_pcall(L, 2, 1, 0);
sum = lua_tonumber(L, -1);
lup_pop(L, -1); //
lua_close(L);
printf("windth:%d height:%d", width, height);
}
/*********.lua文件************
window = {width = 10, height = 20}
function getwidth()
return window.width;
end
function getheight()
return window.height;
end
function getwindow()
return window.width,window.height; --返回两个值
end
function add(a, b)
return a+b;
end
print(a)
**********************/
访问c变量及函数
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
void main()
{
int width = 100;
int height = 200;
lua_State *L = lua_open();
luaopen_base(L);
lua_settop(L, 0);
// 向lua中传入c变量中的width
lua_pushnumber(L, width); // 将width压入栈中
lua_setglobal(L, "width"); // 向栈注册width
// 向lua中传入c变量中的height
lua_pushnumber(L, height);
lua_setglobal(L, "height");
lua_dofile(L, "D:/a_myfile/Lua-test/Lua-test/Debug/test3.lua");
int n = lua_gettop(L);
int d;
scanf("%d", &d);
lua_close(L);
}
/*********.lua文件************
print(width, height);
**********************/
访问表
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
void main()
{
int width = 100;
int height = 200;
lua_State *L = lua_open();
luaopen_base(L);
lua_settop(L, 0); // 把当前栈清空
lua_newtable(L); // 注册表
lua_pushstring(L, "width"); // 创建表的width键
lua_pushnumber(L, width); // 创建表的width值
lua_settable(L, -3); // 设置表
lua_pushstring(L, "height"); // 创建表的height键
lua_pushnumber(L, height); // 创建表的height值
lua_settable(L, -3);
lua_setglobal(L, "t1"); // 将创建的表命名为t1并表注册到lua中
lua_dofile(L, "D:/a_myfile/Lua-test/Lua-test/Debug/test3.lua");
int n = lua_gettop(L);
int d;
scanf("%d", &d);
lua_close(L);
}
/*********.lua文件************
print(t1.width, t1.height);
**********************/
访问函数
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
int width = 100;
int height = 200;
int getwidth(lua_State *L)
{
lua_pushnumber(L, width); // 将width压入栈中
return 1; // 1表示有一个返回值
}
int getheight(lua_State *L)
{
lua_pushnumber(L, height); // 将height压入栈中
return 1; // 1表示有一个返回值
}
void main()
{
lua_State *L = lua_open();
luaopen_base(L);
lua_settop(L, 0); // 把当前栈清空
lua_pushcfunction(L, getwidth); // 将函数压入栈中
lua_setglobal(L, "getwidth"); // 将getwidth函数注册到lua中
lua_pushcfunction(L, getheight); // 将函数压入栈中
lua_setglobal(L, "getheight"); // 将getheight函数注册到lua中
lua_dofile(L, "D:/a_myfile/Lua-test/Lua-test/Debug/test3.lua");
int n = lua_gettop(L);
int d;
scanf("%d", &d);
lua_close(L);
}
/*********.lua文件************
print(getwidth());
*****************************/
函数传参
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
int width = 100;
int height = 200;
// 两个返回值的函数
int getwin(lua_State *L)
{
int scal = lua_tonumber(L, 1); // 获取函数传入的值
lua_pushnumber(L, width); // 将width压入栈中
lua_pushnumber(L, height); // 将height压入栈中
return 2; // 2个返回值
}
void main()
{
lua_State *L = lua_open();
luaopen_base(L);
lua_settop(L, 0); // 把当前栈清空
lua_pushcfunction(L, getwin);
lua_setglobal(L, "getwin");
lua_dofile(L, "D:/a_myfile/Lua-test/Lua-test/Debug/test3.lua");
int n = lua_gettop(L);
int d;
scanf("%d", &d);
lua_close(L);
}
/*********.lua文件************
print(getwin(2)); // 函数传参
*****************************/
使用luaL_openlib()
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
int width = 100;
int height = 200;
// 两个返回值的函数
int getwin(lua_State *L)
{
int scal = lua_tonumber(L, 1); // 获取函数传入的值
lua_pushnumber(L, width); // 将width压入栈中
lua_pushnumber(L, height); // 将height压入栈中
return 2; // 2个返回值
}
int getwidth()
{
lua_pushnumber(L, width);
return 1;
}
// 定义键值对
static const luaL_reg win[] = {
{"getwin", getwin},
{"getwidth", getwidth},
{NULL, NULL}
};
void main()
{
lua_State *L = lua_open();
luaopen_base(L);
lua_settop(L, 0); // 把当前栈清空
luaL_openlib(L, "win", win, 0); // 将函数注册到lua中
lua_dofile(L, "D:/a_myfile/Lua-test/Lua-test/Debug/test3.lua");
int n = lua_gettop(L);
int d;
scanf("%d", &d);
lua_close(L);
}
/*********.lua文件************
print(win.getwin(2), win.getwidth()); // 函数传参
*****************************/
userdata
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include <string.h>
}
typedef struct STR_WIN
{
int width;
int height;
}STR_WIN;
int getwidth(lua_State *L)
{
// 获取lua_touserdata的数据
STR_WIN *p = (STR_WIN *)lua_touserdata(L, -1);
if (p != NULL)
{
lua_pushnumber(L, p->width);
return 1;
}
return 0;
}
int getheight(lua_State *L)
{
// 获取lua_touserdata的数据
STR_WIN *p = (STR_WIN *)lua_touserdata(L, -1);
if (p != NULL)
{
lua_pushnumber(L, p->height);
return 1;
}
return 0;
}
void main()
{
lua_State *L = lua_open();
luaopen_base(L);
lua_settop(L, 0);
// 分配结构体内存块并压栈
STR_WIN *P = (STR_WIN *)lua_newuserdata(L, sizeof(STR_WIN));
P->width = 500;
P->height = 300;
lua_setglobal(L, "win"); // 向lua注册userdata命名为win
lua_pushcfunction(L, getwidth);
lua_setglobal(L, "getwidth");
lua_pushcfunction(L, getheight);
lua_setglobal(L, "getheight");
lua_dofile(L, "D:/a_myfile/Lua-test/Lua-test/Debug/test3.lua");
int d;
scanf("%d", &d);
lua_close(L);
}
/*********.lua文件************
print(getwidth(win));
*****************************/
使用lua_openlib()函数
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include <string.h>
}
typedef struct STR_WIN
{
int width;
int height;
}STR_WIN;
int getwidth(lua_State *L)
{
// 获取lua_touserdata的数据
STR_WIN *p = (STR_WIN *)lua_touserdata(L, -1);
if (p != NULL)
{
lua_pushnumber(L, p->width);
return 1;
}
return 0;
}
int getheight(lua_State *L)
{
// 获取lua_touserdata的数据
STR_WIN *p = (STR_WIN *)lua_touserdata(L, -1);
if (p != NULL)
{
lua_pushnumber(L, p->height);
return 1;
}
return 0;
}
// 定义键值对
static const luaL_reg funlib[] = {
{ "getwidth", getwidth },
{ "getheight", getheight },
{ NULL, NULL }
};
void main()
{
lua_State *L = lua_open();
luaopen_base(L);
lua_settop(L, 0);
STR_WIN *p = (STR_WIN *)lua_newuserdata(L, sizeof(STR_WIN));
p->width = 500;
p->height = 300;
lua_setglobal(L, "win");
luaL_openlib(L, "fun", funlib, 0); // 注册函数数组
lua_dofile(L, "D:/a_myfile/Lua-test/Lua-test/Debug/test3.lua");
int d;
scanf("%d", &d);
lua_close(L);
}
/*****************************
print(fun.getwidth(win), fun.getheight(win)); --500 300
****************************/
使用数组进行访问函数并向函数传参
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include <string.h>
}
typedef struct STR_WIN
{
int width;
int height;
}STR_WIN;
int getwidth(lua_State *L)
{
// 获取lua_touserdata的数据
STR_WIN *p = (STR_WIN *)lua_touserdata(L, -1);
if (p != NULL)
{
lua_pushnumber(L, p->width);
return 1;
}
return 0;
}
int getheight(lua_State *L)
{
// 获取win.meta元表的数据
STR_WIN *p = (STR_WIN *)luaL_checkudata(L, -1, "win.meta");
if (p != NULL)
{
lua_pushnumber(L, p->height);
return 1;
}
return 0;
}
// 定义键值对
static const luaL_reg funlib[] = {
{ "getwidth", getwidth },
{ "getheight", getheight },
{ NULL, NULL }
};
int newObject(lua_State *L)
{
int width = lua_tonumber(L, 1);
int height = lua_tonumber(L, 2);
// 获取win.meta元表的数据
STR_WIN *p = (STR_WIN *)lua_newuserdata(L, sizeof(STR_WIN));
if (p != NULL)
{
p->width = width;
p->height = height;
luaL_getmetatable(L, "win.meta");
lua_setmetatable(L, -2);
return 1;
}
return 0;
}
static const luaL_reg fun[] =
{
{"new", newObject},
{ NULL, NULL }
};
void main()
{
lua_State *L = lua_open();
luaopen_base(L);
lua_settop(L, 0);
luaL_openlib(L, "f", fun, 0); // 注册数组
luaL_openlib(L, "fun", funlib, 0); // 注册函数数组
luaL_newmetatable(L, "win.meta"); // 创建元表
-------------
// 加入这几行,lua文件中则可以写为-->
lua_pushstring(L, "__index");
lua_pushvalue(L, -3); // 将fun压入栈中
lua_settable(L, -3); // 将元表压入栈中
-------------
lua_dofile(L, "D:/a_myfile/Lua-test/Lua-test/Debug/test3.lua");
int d;
scanf("%d", &d);
lua_close(L);
}
/*****************************
local o = f.new(300, 500);
print(fun.getwidth(o), fun.getheight(o));
-->可以写为:
print(o:getwidth(), o:getheight());
****************************/
使用对象定义
STR_WIN.h
#pragma once
class STR_WIN
{
public:
int width;
int height;
};
LUA_STR_WIN.h
#pragma once
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
#include "STR_WIN.h"
class LUA_STR_WIN
{
public:
static int getwidth(lua_State *L);
static int getheight(lua_State *L);
};
LUA_STR_WIN.c
#include "LUA_STR_WIN.h"
int LUA_STR_WIN::getwidth(lua_State *L)
{
// 获取lua_touserdata的数据
STR_WIN **p = (STR_WIN **)luaL_checkudata(L, -1, "win.meta");
if (p != NULL && (*p) != NULL)
{
lua_pushnumber(L, (*p)->width);
return 1;
}
return 0;
}
int LUA_STR_WIN::getheight(lua_State *L)
{
// 获取win.meta元表的数据
STR_WIN **p = (STR_WIN **)luaL_checkudata(L, -1, "win.meta");
if (p != NULL && (*p) != NULL)
{
lua_pushnumber(L, (*p)->height);
return 1;
}
return 0;
}
main.c
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
#include <string.h>
#include "STR_WIN.h"
#include "LUA_STR_WIN.h"
// 定义键值对
static const luaL_reg funlib[] = {
{ "getwidth", LUA_STR_WIN::getwidth },
{ "getheight", LUA_STR_WIN::getheight },
{ NULL, NULL }
};
int newObject(lua_State *L)
{
int width = lua_tonumber(L, 1);
int height = lua_tonumber(L, 2);
// 创建userdata对象
STR_WIN **p = (STR_WIN **)lua_newuserdata(L, sizeof(STR_WIN*));
*p = new STR_WIN();
if (p != NULL && (*p) != NULL)
{
(*p)->width = width;
(*p)->height = height;
luaL_getmetatable(L, "win.meta");
lua_setmetatable(L, -2);
return 1;
}
return 0;
}
// 对定义的对象进行垃圾回收
int DestroyObject(lua_State *L)
{
// 获取lua_touserdata的数据
STR_WIN **p = (STR_WIN **)luaL_checkudata(L, -1, "win.meta");
if (p != NULL && (*p) != NULL)
{
delete *p;
}
return 0;
}
static const luaL_reg fun[] =
{
{"new", newObject},
{ NULL, NULL }
};
void main()
{
lua_State *L = lua_open();
luaopen_base(L);
lua_settop(L, 0);
luaL_openlib(L, "f", fun, 0); // 注册数组
luaL_openlib(L, "fun", funlib, 0); // 注册函数数组
luaL_newmetatable(L, "win.meta"); // 创建元表
// index方法
lua_pushstring(L, "__index");
lua_pushvalue(L, -3); // 将fun压入栈中
lua_settable(L, -3); // 将元表压入栈中
// 垃圾回收
lua_pushstring(L, "__gc");
lua_pushcfunction(L, DestroyObject);
lua_settable(L, -3);
lua_dofile(L, "D:/a_myfile/Lua-test/Lua-test/Debug/test3.lua");
int d;
scanf("%d", &d);
lua_close(L);
}
