从C中更改lua变量
2015-6-24 12:0:2
收藏:0
阅读:71
评论:4
我有一个主程序(用C编写),它需要分支到lua_thread(主程序继续运行)。这个lua_thread调用一个lua_script.lua。这个lua_script包含一个while循环。一个lua变量控制这个while循环。目前这个循环永远不会停止运行。
lua_script.lua
--this loop runs forever, as the exit value is not set yet
a=0
while(a<=0)
do
print("value of a:", a)
end
我的目标是从主程序更改这个lua变量(a),使其退出这个无限循环。一旦循环结束,它就会退出线程并返回到主程序。
main.c
#include <lua.h>
#include <lauxlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
void *lua_thread()
{
int status, result;
double sum;
lua_State *L;
L = luaL_newstate();
luaL_openlibs(L);
status = luaL_loadfile(L, "lua_script.lua");
if (status)
{
fprintf(stderr, "Couldn't load file: %s\n", lua_tostring(L, -1));
exit(1);
}
result = lua_pcall(L, 0, 0, 0);
if (result) {
fprintf(stderr, "Failed to run script: %s\n", lua_tostring(L, -1));
exit(1);
}
lua_close(L);
return 0;
}
int main(void)
{
pthread_t p1;
pthread_create(&p1,NULL,lua_thread,NULL);
pthread_join(p1,NULL);
return 0;
}
如果你运行上面的代码
cc -o xcute main.c -I/usr/include/lua5.2 -llua -lm -ldl -pthread
它将进入一个无限循环。我想以某种方式控制lua变量并将其更改为a = 1,从主程序中使其退出无限循环。进行这样的测试的原因是,它将确保在主程序退出之前,通过控制lua变量,先退出此线程。
请建议如何更改这个lua变量,使其退出while循环。
点赞
用户3125367
为什么要在 Lua 中循环?你可以使用 c-thread 循环,每次迭代都通过 lua_pcall 调用某个入口函数(例如 onEvent())。
如果必须在 Lua 脚本中使用循环,例如在设置-循环-清理结构的情况下,可以在协程中运行脚本并使用 coroutine.yield() 作为循环条件。线程应该使用 true 值或退出的 lua_resume(),具体取决于你的 c-side 条件。(或者如果首选循环后 Lua-side 清理的话,则使用 false 再次恢复。)
无论如何,Lua 不支持多线程,不能同时从多个线程调用。
2015-06-24 17:34:28
用户4374077
Lua 线程中使用信号量退出
main.c
#include <lua.h>
#include <lauxlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <assert.h>
#include <fcntl.h>
#include <semaphore.h>
void *lua_thread(void *arg)
{
int status, result, i;
double sum;
lua_State *L = (lua_State *)arg;
int a = 0;
status = luaL_dofile(L, "lua_script.lua");
if (status) {
fprintf(stderr, "Couldn't load file: %s\n", lua_tostring(L, -1));
exit(1);
}
printf("Lua thread exiting\n");
return 0;
}
int main(void)
{
lua_State *L;
L = luaL_newstate();
luaL_openlibs(L);
// 打开信号量,该信号量将会通知 Lua 循环退出
sem_t *lex = sem_open("luaexitsem", O_CREAT, 0600, 0);
// 在开始运行之前,确保信号量的值为 0,
// 这样 sem_post 就会将它设置为 1
int retval;
for (retval = 0; retval == 0;) {
retval = sem_trywait(lex);
printf("Dec sem val: %d\n", retval);
}
// 启动 Lua 线程
pthread_t p1;
pthread_create(&p1, NULL, lua_thread, L);
sleep(5);
// 发出信号告知 Lua 脚本退出
sem_post(lex);
// 等待 Lua 线程退出
pthread_join(p1, NULL);
// 清理
printf("Main exiting\n");
lua_close(L);
sem_close(lex);
return 0;
}
编译命令
gcc -o main main.c -I/usr/include/lua5.1 -llua5.1 -lm -ldl -pthread
lua_script.lua
require "lualinuxthread"
a = 1
while (not linuxthread.signaltoexit()) do
print("value of a:", a)
a = a + 1
end
lualinuxthread.c
#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
#include <semaphore.h>
#include <errno.h>
#include <fcntl.h>
static int signaltoexit(lua_State *L)
{
sem_t *lex = sem_open("luaexitsem", O_CREAT, 0600, 0);
int exitvalue = 0, retval;
if (lex != SEM_FAILED)
retval = sem_trywait(lex);
if (retval == -1)
exitvalue = 0;
else
exitvalue = 1;
printf("signaltoexit - exitvalue: %d, retval: %d, %x\n", exitvalue, retval, lex);
lua_pushboolean(L, exitvalue);
sem_close(lex);
return 1;
}
static const luaL_Reg libfuncs[] = {
{"signaltoexit", signaltoexit},
{NULL, NULL}};
LUALIB_API int luaopen_lualinuxthread(lua_State *L)
{
luaL_register(L, "linuxthread", libfuncs);
return 1;
}
编译命令
gcc -O -O2 -fpic -shared lualinuxthread.c -o lualinuxthread.so -lpthread -llua5.1
感谢!
2015-06-26 11:10:34
用户3125367
哦,你在回答中走了一条艰难的道路(当然这也是一个很好的练习)。事情可能要简单得多:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
static volatile int shouldRun = 1; // 1.
static int
fn_sleep(lua_State *L)
{
lua_Integer n = luaL_checkinteger(L, 1);
sleep(n < 0 ? 0 : n);
return 0;
}
static int
fn_shouldRun(lua_State *L)
{
lua_pushboolean(L, shouldRun);
return 1;
}
static void *
thread_main(void *dummy)
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_register(L, "sleep", fn_sleep); // 2.
lua_register(L, "shouldRun", fn_shouldRun);
if (luaL_dofile(L, "script.lua")) {
fprintf(stderr, "%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
}
lua_close(L); // 3.
return 0;
}
int
main(int argc, char *argv[])
{
pthread_t thread;
pthread_create(&thread, NULL, thread_main, NULL);
sleep(5);
shouldRun = 0; // 1.
pthread_join(thread, NULL);
return 0;
}
script.lua:
print("Hi!")
while shouldRun() do
print("Running!")
sleep(1)
end
print("Bye!")
output:
Hi!
Running!
Running!
Running!
Running!
Running!
Bye!
需要注意几点:
- 轮询的退出条件通常不需要任何保护措施。如果
shouldRun()同时与变量更新被调用并且错过了它,那么无需担心-它将在下一次返回 false。无论如何,你甚至无法猜测脚本在哪里执行,只需要重置该值并等待完成。 - 对于一对特定的函数,无需编写与
require/preload兼容的模块。将它们导出到全局命名空间中。 - 对于优雅的错误关闭,不要仅使用
exit()。lua_close()将收集脚本使用的所有UserData,它们的__gc元方法可能会做一些有用的事情,如将缓冲区刷新到磁盘等。硬退出会失去所有机会。
2015-06-26 16:44:42
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
从不同的线程与运行中的lua状态交互不一定安全
因此,根据您计划从C端进行更改的位置,修改脚本的全局变量可能是一个好主意,也可能不是。
如果要这样做,您只需要使用lua C api在适当的lua状态中设置适当名称的全局变量即可。
另一种想法是创建一个
should_exit全局函数,在每个循环的开头或结尾调用它,当它返回true时,会导致lua代码“break”或“return”。然后,该函数可以以线程适当的方式在C端检查任何所需的内容。