Easyx图形库应用(lua中的函数回调)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

用lua脚本做软件开发还是非常方便的。中间需要做的,就是把自己的c/c++代码转成lua函数即可。这样开发中的大部分问题,就会转成脚本开发的问题。但是还有一种情况比较难处理,那就是c语言中的回调函数。在lua中,应该怎么处理回调函数呢?

1、准备一个lua文件

首先,我们准备一个lua文件,文件中只有一个函数。所以如果只是单纯执行这个lua文件,什么也不会进行处理,

复制代码
-- function defined here
function add(x, y)
	debug()
    return x + y
end

2、lua文件中的debug函数

为了确认add函数被执行到了,我们又注册了一个debug函数。这样可以在执行的时候,单步确认一下,add函数是不是肯定被执行到了,

复制代码
lua_register(L, "debug", (lua_CFunction)&debug_function);

debug_function简单实现一下即可,

复制代码
static void debug_function(lua_State* L) // check if lua function was invoked already
{
	printf("debug info here\n");
}

3、加载并执行lua文件

执行lua文件前,一般需要创建虚拟机、加载标准库、注册函数,这些都是常规动作。这些都做好之后,就是执行lua文件。因为lua文件中只有函数声明,没有函数调用,所以很快就返回了。luaL_loadfile+lua_pcall其实就是luaL_dofile。

复制代码
	if (luaL_loadfile(L, "./demo.lua") || lua_pcall(L, 0, 0, 0)) 
	{
		printf("failed to load test.lua: %s\n", lua_tostring(L, -1));
		lua_close(L);
		return -1;
	}

4、查找add函数,赋值参数,并调用

下面要做的就是找到add函数,并且给它参数,验证结果即可。

复制代码
	lua_getglobal(L, "add");  
	if (!lua_isfunction(L, -1)) 
	{
		printf("failed to find add function in lua file!\n");
		lua_close(L);
		return -1;
	}

	lua_pushnumber(L, 10);
	lua_pushnumber(L, 20); 

	if (lua_pcall(L, 2, 1, 0) != LUA_OK)
	{
		printf("invoke add failed: %s\n", lua_tostring(L, -1));
		lua_close(L);
		return -1;
	}

	if (lua_isnumber(L, -1)) 
	{
		double result = lua_tonumber(L, -1);
		printf("result:%f\n", result);
	}

	lua_pop(L, 1); // pop result here

这里面最重要的函数就是lua_getglobal,它相当于在lua字节码里面找到函数,并压栈处理。接下来就是继续压入10和20,最终通过lua_pcall执行这个函数。注意,这里压入的都是浮点数。执行完毕后,确认返回值是否是浮点数,以及弹出数据即可。

如果希望处理的是整数,那么代码应该这么写,

复制代码
	lua_getglobal(L, "add");  
	if (!lua_isfunction(L, -1)) 
	{
		printf("failed to find add function in lua file!\n");
		lua_close(L);
		return -1;
	}

	lua_pushinteger(L, 10);
	lua_pushinteger(L, 20); 

	if (lua_pcall(L, 2, 1, 0) != LUA_OK) // key function
	{
		printf("invoke add failed: %s\n", lua_tostring(L, -1));
		lua_close(L);
		return -1;
	}

	if (lua_isinteger(L, -1)) 
	{
		int result = (int)lua_tointeger(L, -1);
		printf("result:%d\n", result);
	}

	lua_pop(L, 1); // pop result here

5、单步调试

为了确认add函数是什么时候执行的,我们添加了一个debug函数,可以在main函数里面设置一些断点。通过单步调试的方式,就知道lua中的add函数是什么时候执行的了。

6、在实际c函数中的应用

实际使用的时候,我们一般也会专门注册一个c回调函数。所以如果逻辑走到回调的时候,一般是先进入这个专门的回调函数,然后在专门的回调函数里面,再通过L、lua_getglobal & luapcall去执行对应的lua函数。

7、完整代码

最后给出完整的c代码,有兴趣的同学可以好好测试下。

复制代码
#include <stdio.h>
#include "lua.hpp"

static void debug_function(lua_State* L) // check if lua function was invoked already
{
	printf("debug info here\n");
}

int main(int argc, char* argv[])
{
	lua_State *L = luaL_newstate();

	// register function here

	luaL_openlibs(L);
	lua_register(L, "debug", (lua_CFunction)&debug_function);

	if (luaL_loadfile(L, "./demo.lua") || lua_pcall(L, 0, 0, 0)) 
	{
		printf("failed to load test.lua: %s\n", lua_tostring(L, -1));
		lua_close(L);
		return -1;
	}

	lua_getglobal(L, "add");  
	if (!lua_isfunction(L, -1)) 
	{
		printf("failed to find add function in lua file!\n");
		lua_close(L);
		return -1;
	}

	lua_pushinteger(L, 10);
	lua_pushinteger(L, 20); 

	if (lua_pcall(L, 2, 1, 0) != LUA_OK) // key function
	{
		printf("invoke add failed: %s\n", lua_tostring(L, -1));
		lua_close(L);
		return -1;
	}

	if (lua_isinteger(L, -1)) 
	{
		int result = (int)lua_tointeger(L, -1);
		printf("result:%d\n", result);
	}

	lua_pop(L, 1); // pop result here
	lua_close(L);

	return 0;
}
相关推荐
平常心的技术小牛2 分钟前
Qt-快速上手-QMenuBar
开发语言·qt
青 春 记 忆27 分钟前
零基础入门Python11|Git实战:为任务管理器建立版本历史
开发语言·git·vscode·python·python3.11
余额瞒着我当琳2 小时前
C++--深拷贝三件套 + swap + 写时拷贝 + vector 扩容 + reserve
java·开发语言·c++
坐吃山猪3 小时前
WebClient内存配置解析
开发语言·springboot·webflux
jdksjw3 小时前
同步与异步、阻塞与非阻塞、多线程、协程超详细讲解(Python并发编程从入门到精通)
开发语言·python
Zach_菠萝侠3 小时前
【DeepSeek Harness 研究】进化方向4:安全加固 思考、设计与实现
开发语言·安全·deepseek
SL-staff4 小时前
技术实践:HR如何用JVS-Logic可视化编排实现考勤数据同步(含节点配置与异常处理)
开发语言·python·低代码·钉钉·可视化编排·jvs-logic·hr技术
SomeB1oody4 小时前
【RustyML入门】6.0. 数学工具
开发语言·后端·机器学习·rust·教程
进制树5 小时前
【飞控开发实战·⑲】ROS2无人机开发环境搭建:Jazzy安装、工作空间与hello_drone节点实战
开发语言·安全·无人机·课程设计
牛马也想出海6 小时前
亚马逊爬虫代理IP:IP类型选择与配置指南
开发语言·php