链表实现

  1. t = {1, 2, 3, 4, 5, 6}
  2. n = table.getn(t); --表的长度
  3. list = null;
  4. for i = 1, n do
  5. list = {val = t[i], next = list}
  6. end
  7. -- 自定义ipairs接口
  8. function ipairs_iter(t, node)
  9. if node == nil then return t;
  10. else return node.next
  11. end
  12. end
  13. function ipairs_list(t)
  14. return ipairs_iter, t, nil
  15. end
  16. -- 遍历
  17. for node in ipairs_list(list) do
  18. print(node.val)
  19. end
  20. -- 删除链表中的某个
  21. function delnode(list, val)
  22. for node in ipairs_list(list) do
  23. local preNode = node; -- 上一个节点
  24. local curNode = node.next; -- 当前节点
  25. if curNode ~= nil and curNode.val == val then
  26. local nextNode = curNode.next; -- 下一个节点
  27. preNode.next = nextNode;
  28. curNode = nil;
  29. end
  30. end
  31. end
  32. delnode(list, 3); -- 删除list中值为3的元素
  33. -- 遍历
  34. for node in ipairs_list(list) do
  35. print(node.val)
  36. end

lua元表

  1. a = {1, 2, 3}
  2. b = {2, 3, 4}
  3. --定义元表
  4. mt = {}
  5. --定义元表相加方法
  6. mt.__add = function(a, b)
  7. local len = table.getn(a);
  8. local res = {}
  9. for i = 1, len do
  10. res[i] = a[i] + b[i];
  11. end
  12. return res;
  13. end
  14. --定义元表相连方法
  15. mt.__concat = function(a, b)
  16. local len = table.getn(a);
  17. local res = {};
  18. for i = 1, len do
  19. res[i] = a[i] .. b[i]
  20. end
  21. return res;
  22. end
  23. --定义等于方法
  24. mt.__eq = function(a, b)
  25. local len = table.getn(a);
  26. local res = false;
  27. for i = 1, len do
  28. if a[i] ~= b[i] then
  29. res = true;
  30. break;
  31. end
  32. end
  33. if res == false then
  34. return true
  35. else
  36. return false;
  37. end
  38. end
  39. --设置ab的元表
  40. setmetatable(a, mt);
  41. setmetatable(b, mt);
  42. c = a + b;
  43. for k,v in ipairs(c) do
  44. print(v); -- 3 5 7
  45. end
  46. d = a .. b;
  47. local len = table.getn(d);
  48. for i = 1, len do
  49. print(d[i]); --12 23 34
  50. end
  51. -----------------------------
  52. --index表示当在mywindow没有找到元素时,会在父表中寻找
  53. Window = {x = 0, y = 0, width = 100, height = 200}
  54. Window.__index = function(t, key)
  55. return Window[key];
  56. end
  57. --当去修改元表中的值时,用的是newindex
  58. Window.__newindex = function(t, k, v)
  59. Window[k] = v;
  60. end
  61. myWindow = {};
  62. setmetatable(myWindow, Window);
  63. printf(myWindow.width); --100 没有找到会在父表中寻找
  64. printf(rawget(myWindow, width)); --nil 只在自己的表中查询
  65. myWindow.test = 1000; --设置在了父元素上
  66. printf(myWindow.test); --1000
  67. printf(rawget(myWindow, test)); --nil
  68. ---------------------------
  69. --定义字符串方法
  70. Window.__tostring = function(t)
  71. local len = table.getn(t);
  72. local s = "";
  73. for i = 1, len do
  74. s = s .. ",";
  75. end
  76. end

lua环境表

  1. --防止在函数内部定义全局变量
  2. -- 教程:https://www.bilibili.com/video/BV1Zz411i7QW?p=12
  3. local declaredNames = {}
  4. local mt = {
  5. __newindex = function(table, name, value)
  6. --先检查新的名字是否已经声明过,如果存在,这直接通过rawset函数设置即可
  7. if not declaredNames[name] then
  8. --再检查本次操作是否是再主程序或者C代码中完成的,如果是,就继续设置,否在报错
  9. local w = debug.getinfo(2, "S").what
  10. if w ~= "main" and w ~= "C" then
  11. print(w)
  12. error("attempt to write to undeclared variable" .. name);
  13. end
  14. --在实际设置之前,更新一下declaredNames表,下次再设置时就无需检查了
  15. declaredNames[name] = true;
  16. end
  17. print("Setting " .. name .. " to " .. value);
  18. rawset(table, name, value);
  19. end,
  20. __index = function(_,name)
  21. if not declaredNames[name] then
  22. error("attempt to read undeclared variable " .. name)
  23. else
  24. return rawget(_,name)
  25. end
  26. end
  27. }
  28. setmetatable(_G,mt);
  29. a = 11
  30. local kk = aa --报错 不能将全局变量赋值给局部变量

lua package包

  1. for k,v in pairs(package.loaded) do
  2. print(k,v)
  3. end
  4. print("-----------------------");
  5. for k,v in pairs(package.preload) do
  6. print(k,v)
  7. end
  8. --print(package.path); --寻找包路径
  9. require "mathlib" --查找mathlib文件
  10. --require执行流程
  11. --1.首先在package.loaded查找modelname
  12. --2.packagepreload查找modelname,如果preload存在,那就把它作为loader,调用loader[L]
  13. --3.根据package.path查找lua文件
  14. --4.根据package.cpath查找c库,并调用相应名字的接口

—mathilb.lua文件

  1. local P = {} --未加local则会被调用的文件给覆盖了
  2. mathlib = P
  3. function P.add(a, b)
  4. return a + b
  5. end
  6. function P.sub(a, b)
  7. return a-b
  8. end
  9. function P.sum(...)
  10. local _sum = 0
  11. for k = 1, arg.n do
  12. _sum = P.add(_sum, arg[k])
  13. end
  14. return _sum;
  15. end
  16. return P;

另一种写法

  1. ---------------------
  2. --local libname = ...
  3. local P = {}
  4. mathlib = P; --另一种 _G[libname] = P;
  5. setmetatable(P, {__index = _G});
  6. setfenv(1, P);
  7. --module(...) 上面的功能lua内部封装好了module(...)
  8. -----------------------
  9. function add(a, b)
  10. return a+b;
  11. end
  12. function sub(a,b)
  13. return a-b;
  14. end
  15. function sum(...)
  16. local _sum = 0;
  17. for k = 1, arg.n do
  18. _sum = add(_sum, arg[k])
  19. end
  20. return _sum;
  21. end
  22. ------------
  23. return P;
  24. ------------

—test.lua文件

  1. mathlib = {x = 100}
  2. print(mathlib.x)
  3. local lib = require "mathlib"
  4. print(lib.sum(1,2,3,4,5,6,7,8))
  5. print(mathlib.x)
  6. --100 36 100(如果被调用的文件mathlib不是local变量时,则为nil

面向对象设计

  1. CPeople = {name = "default name", age = 10, sex = "fale"}
  2. function CPeople.new(p, o)
  3. o = o or {}
  4. setmetatable(o, p)
  5. p.__index = p;
  6. return o;
  7. end
  8. function CPeople.Walk()
  9. print("walk");
  10. end
  11. function CPeople.Say()
  12. print("Say");
  13. end
  14. function CPeople.Print(p)
  15. p = p or CPeople;
  16. print(p.name, p.age);
  17. end
  18. --子类实现 并继承父类
  19. CMale = {}
  20. function CMale:new(o)
  21. o = o or {}
  22. setmetatable(o, self);
  23. self.__index = self;
  24. setmetatable(self, CPeople); --继承CPeople类的属性和方法
  25. CPeople.__index = CPeople;
  26. end
  27. local p1 = CPeople.new(CPeople, {name = "zhanshang", age = 10});
  28. p1.Walk(); --walk
  29. p1.Print(); --default name 10
  30. p1.Print(p1); --zhanshang 10
  31. local p2 = CMale:new();
  32. p2:Walk(); --walk 若自己没有定义,则来自父类的方法
  33. /*---------------------------------------------------------------------
  34. --可以隐藏掉第一个参数
  35. function CPeople:new( o)
  36. o = o or {}
  37. setmetatable(o, self)
  38. self.__index = self;
  39. return o;
  40. end
  41. function CPeople:Walk()
  42. print("walk");
  43. end
  44. function CPeople:Say()
  45. print("Say");
  46. end
  47. function CPeople:Print()
  48. print(self.name, self.age);
  49. end
  50. --隐藏掉的第一个参数调用
  51. local p1 = CPeople:new({name = "zhanshang", age = 10});
  52. p1:Walk();
  53. p1:Print();
  54. --walk
  55. --zhanshang 10
  56. ---------------------------------------------------------------------*/

弱表

--手动回收函数
--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);
}