使用C语言操作LUA栈

目录

参考

接上文https://blog.csdn.net/qq_42039294/article/details/139806522

本文内容主要参考https://www.bilibili.com/video/BV1UR4y1P7Nd/

简介

为了方便测试,本文把LUA部署在电脑上,在电脑上测试而不是上文单片机中测试。操作流程没有区别

lua向C传递的参数由填写在lua函数中的形参给定,这些形参首先会进入lua虚拟栈中,虚拟栈句柄指针再传递到C函数中,由C函数做弹出参数或者压入参数的操作

C函数的返回值指定LUA函数返回参数数量。LUA函数返回参数也来自于虚拟栈

以my_lua_add(a, b)函数为例,该功能用于再lua中实现a+b,然后将结果返回,处理流程如下:

C函数返回值

C函数返回值

C函数检查并读取虚拟栈内数据

表中arg位置就是栈索引idx,为了匹配lua中文手册,描述为arg

函数名 作用
luaL_checkany 检查arg位置是否有参数,包括nil,如果没有的触发错误
luaL_checkinteger 检查arg位置是否为整形数字或者可以转换为整型数字,如果没有的触发错误 "转换"的例子:33, "33", 33.0, 不可"转换"的例子:"a", 33.2
luaL_checknumber 浮点型数字或者可转换为浮点型数字
luaL_checkstring 字符串类型或者可转换为字符串类型,如果匹配,返回字符串指针,如果不匹配抛出错误
luaL_checklstring 字符串类型或者可转换为字符串类型,如果匹配,那么将字符串长度传入形参中,返回字符串指针,如果不匹配抛出错误
luaL_checktype 检查类型是否匹配形参t
luaL_checkoption 似乎用来做命令行选项的,C维护一个选项-递增枚举值表格,传入之后,当lua指令带形参的时候,返回枚举值
luaL_checkstack 扩展栈空间
...

check type枚举值

c 复制代码
#define LUA_TNONE           (-1)
#define LUA_TNIL             0
#define LUA_TBOOLEAN         1
#define LUA_TLIGHTUSERDATA   2
#define LUA_TNUMBER          3
#define LUA_TSTRING          4
#define LUA_TTABLE           5
#define LUA_TFUNCTION        6
#define LUA_TUSERDATA        7
#define LUA_TTHREAD          8

测试

c 复制代码
#include "stdio.h"
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

static int function_pp (lua_State *L) {
    printf("1 arg is %f\r\n", luaL_checknumber(L, 1));
    printf("2 arg is %I64d\r\n", luaL_checkinteger(L, 2));
    printf("3 arg is %s\r\n", luaL_checkstring(L, 3));
    return 0;
}

static const luaL_Reg extlib[] = {
    {"pp", function_pp},
    {NULL, NULL}
};

int luaopen_ext (lua_State *L) {
    luaL_newlib(L, extlib);
    return 1;
}
复制代码
PS C:\Users\Administrator\Desktop\lua> mingw32-make.exe
========== Running app.exe ==========
./app.exe
Lua 5.4.8  Copyright (C) 1994-2025 Lua.org, PUC-Rio
> ext.pp(33.5, 666, "ddml")
1 arg is 33.500000
2 arg is 666
3 arg is ddml

check + 默认值

函数名 作用
luaL_optinteger 如果arg是一个整数或者可以转换为一个整数,返回该整数。 若该参数不存在或是 nil, 返回形参d。 除此之外的情况,抛出错误
luaL_optlstring
luaL_optnumber
luaL_optstring

测试

c 复制代码
static int function_pp (lua_State *L) {
    int cnum = luaL_optinteger(L, 1, 8848);
    printf("cnum = %d\n", cnum);
    return 0;
}
复制代码
PS C:\Users\winston\Desktop\TEST\lua> .\app.exe       
Lua 5.4.8  Copyright (C) 1994-2025 Lua.org, PUC-Rio
> ext.pp()
cnum = 8848
> ext.pp(1)
cnum = 1
> ext.pp(nil) 
cnum = 8848
> ext.pp("string")
stdin:1: bad argument #1 to 'pp' (number expected, got string)
stack traceback:
        [C]: in function 'ext.pp'
        stdin:1: in main chunk
        [C]: in ?

C函数判断虚拟栈内数据类型

函数名 作用
lua_isboolean
lua_iscfunction
lua_isfunction
lua_isinteger
lua_islightuserdata
lua_isnil
lua_isnone
lua_isnoneornil
lua_isnumber
lua_isstring
lua_istable
lua_isthread
lua_isuserdata
lua_isyieldable

测试

c 复制代码
static int function_pp (lua_State *L) {
    printf("%s\n",lua_isinteger(L, 1) ?"is int":"not int");
    return 0;
}
复制代码
PS C:\Users\winston\Desktop\TEST\lua> .\app.exe       
Lua 5.4.8  Copyright (C) 1994-2025 Lua.org, PUC-Rio
> ext.pp(1)
is int
> ext.pp(1.0) 
not int
> ext.pp("string")
not int
> ext.pp()         
not int

C函数栈数据类型转换

函数名 作用
lua_toboolean false,nil, 空值是假的,其余是真
lua_tocfunction
lua_tointeger
lua_tointegerx 相比于lua_tointeger,多一个指针用来传递是否转换成功
lua_tostring
lua_tolstring
lua_tonumber
lua_tonumberx
lua_topointer
lua_tothread
lua_touserdata

测试代码

c 复制代码
static int function_pp (lua_State *L) {
    printf("%s", lua_toboolean(L, 1) ? "TRUE\n" : "FALSE\n");
    return 0;
}
复制代码
PS C:\Users\winston\Desktop\TEST\lua> .\app.exe       
Lua 5.4.8  Copyright (C) 1994-2025 Lua.org, PUC-Rio
TRUE
TRUE
> ext.pp(true) ext.pp(false)
TRUE
FALSE
> ext.pp(nil) ext.pp()
FALSE
FALSE

C函数推入数据

函数名 作用
lua_pushboolean 推入bool型
lua_pushnil 推入nil
lua_pushnumber 推入浮点形
lua_pushinteger 推入整形
lua_pushfstring 推入格式化字符串, (相比于snprintf功能不完善,不建议使用)
lua_pushliteral 推入字符串,字符串必须是字面量
lua_pushlstring 推入字符串,带长度
lua_pushstring 推入字符串
lua_pushvfstring 等同于pushfstring,但是使用valist接收参数
lua_pushvalue 栈中某个索引的栈值复制一份,放到栈顶

测试

c 复制代码
static int function_pp (lua_State *L) {
    lua_pushnil(L);
    lua_pushboolean(L, 1);
    lua_pushnumber(L, 666.88);
    lua_pushinteger(L, 342);
    lua_pushstring(L, "pp");
    lua_pushvalue(L, 1);
    return 6;
}
复制代码
PS C:\Users\winston\Desktop\TEST\lua> .\app.exe
Lua 5.4.8  Copyright (C) 1994-2025 Lua.org, PUC-Rio
> ext.pp()
nil     true    666.88  342     pp      nil
相关推荐
东华万里3 小时前
第十五讲 指针 从本质吃透 C 语言指针(上)
c语言·开发语言
Logic1013 小时前
深入理解C语言if语句的汇编实现原理:从条件判断到底层跳转
c语言·汇编语言·逆向工程·底层原理·条件跳转·编译器原理·x86汇编
恶魔泡泡糖3 小时前
最小系统组成部分
c语言·单片机
iCxhust4 小时前
8088单板机C语言汇编混合编程实验方法与步骤
c语言·汇编·单片机·嵌入式硬件·微机原理
雨落在了我的手上4 小时前
C语言入门(二十八):动态内存管理(2)
c语言·开发语言
小龙报5 小时前
【算法通关指南:基础算法篇】高精度专题:一篇破除超数运算问题
c语言·数据结构·c++·算法·链表·贪心算法·visual studio
Yupureki5 小时前
《算法竞赛从入门到国奖》算法基础:入门篇-双指针
c语言·开发语言·数据结构·c++·算法·visual studio
努力努力再努力wz5 小时前
【Linux网络系列】:网络+网络编程(UDPsocket+TCPsocket)
java·linux·c语言·开发语言·数据结构·c++·centos