链表实现
t = {1, 2, 3, 4, 5, 6}
n = table.getn(t); --表的长度
list = null;
for i = 1, n do
list = {val = t[i], next = list}
end
-- 自定义ipairs接口
function ipairs_iter(t, node)
if node == nil then return t;
else return node.next
end
end
function ipairs_list(t)
return ipairs_iter, t, nil
end
-- 遍历
for node in ipairs_list(list) do
print(node.val)
end
-- 删除链表中的某个
function delnode(list, val)
for node in ipairs_list(list) do
local preNode = node; -- 上一个节点
local curNode = node.next; -- 当前节点
if curNode ~= nil and curNode.val == val then
local nextNode = curNode.next; -- 下一个节点
preNode.next = nextNode;
curNode = nil;
end
end
end
delnode(list, 3); -- 删除list中值为3的元素
-- 遍历
for node in ipairs_list(list) do
print(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 do
res[i] = a[i] + b[i];
end
return res;
end
--定义元表相连方法
mt.__concat = function(a, b)
local len = table.getn(a);
local res = {};
for i = 1, len do
res[i] = a[i] .. b[i]
end
return res;
end
--定义等于方法
mt.__eq = function(a, b)
local len = table.getn(a);
local res = false;
for i = 1, len do
if a[i] ~= b[i] then
res = true;
break;
end
end
if res == false then
return true
else
return false;
end
end
--设置a,b的元表
setmetatable(a, mt);
setmetatable(b, mt);
c = a + b;
for k,v in ipairs(c) do
print(v); -- 3 5 7
end
d = a .. b;
local len = table.getn(d);
for i = 1, len do
print(d[i]); --12 23 34
end
-----------------------------
--index表示当在mywindow没有找到元素时,会在父表中寻找
Window = {x = 0, y = 0, width = 100, height = 200}
Window.__index = function(t, key)
return Window[key];
end
--当去修改元表中的值时,用的是newindex
Window.__newindex = function(t, k, v)
Window[k] = v;
end
myWindow = {};
setmetatable(myWindow, Window);
printf(myWindow.width); --100 没有找到会在父表中寻找
printf(rawget(myWindow, width)); --nil 只在自己的表中查询
myWindow.test = 1000; --设置在了父元素上
printf(myWindow.test); --1000
printf(rawget(myWindow, test)); --nil
---------------------------
--定义字符串方法
Window.__tostring = function(t)
local len = table.getn(t);
local s = "";
for i = 1, len do
s = s .. ",";
end
end
lua环境表
--防止在函数内部定义全局变量
-- 教程:https://www.bilibili.com/video/BV1Zz411i7QW?p=12
local declaredNames = {}
local mt = {
__newindex = function(table, name, value)
--先检查新的名字是否已经声明过,如果存在,这直接通过rawset函数设置即可
if not declaredNames[name] then
--再检查本次操作是否是再主程序或者C代码中完成的,如果是,就继续设置,否在报错
local w = debug.getinfo(2, "S").what
if w ~= "main" and w ~= "C" then
print(w)
error("attempt to write to undeclared variable" .. name);
end
--在实际设置之前,更新一下declaredNames表,下次再设置时就无需检查了
declaredNames[name] = true;
end
print("Setting " .. name .. " to " .. value);
rawset(table, name, value);
end,
__index = function(_,name)
if not declaredNames[name] then
error("attempt to read undeclared variable " .. name)
else
return rawget(_,name)
end
end
}
setmetatable(_G,mt);
a = 11
local kk = aa --报错 不能将全局变量赋值给局部变量
lua package包
for k,v in pairs(package.loaded) do
print(k,v)
end
print("-----------------------");
for k,v in pairs(package.preload) do
print(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 = P
function P.add(a, b)
return a + b
end
function P.sub(a, b)
return a-b
end
function P.sum(...)
local _sum = 0
for k = 1, arg.n do
_sum = P.add(_sum, arg[k])
end
return _sum;
end
return 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;
end
function sub(a,b)
return a-b;
end
function sum(...)
local _sum = 0;
for k = 1, arg.n do
_sum = add(_sum, arg[k])
end
return _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;
end
function CPeople.Walk()
print("walk");
end
function CPeople.Say()
print("Say");
end
function 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;
end
local p1 = CPeople.new(CPeople, {name = "zhanshang", age = 10});
p1.Walk(); --walk
p1.Print(); --default name 10
p1.Print(p1); --zhanshang 10
local p2 = CMale:new();
p2:Walk(); --walk 若自己没有定义,则来自父类的方法
/*---------------------------------------------------------------------
--可以隐藏掉第一个参数
function CPeople:new( o)
o = o or {}
setmetatable(o, self)
self.__index = self;
return o;
end
function CPeople:Walk()
print("walk");
end
function CPeople:Say()
print("Say");
end
function 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);
}