Tengo un programa principal (en C) que necesita ramificarse en lua_thread (el principal continúa ejecutándose). Este lua_thread llama a lua_script.lua. este lua_script contiene un ciclo while. una variable lua controla este ciclo while. Actualmente, este ciclo se ejecuta para siempre.
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) endMi objetivo es cambiar esta variable lua (a) del programa principal para que salga de este ciclo infinito. Una vez que finaliza este bucle, sale del hilo y vuelve al programa principal.
C Principal
#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; }Si ejecuta el código anterior
cc -o xcute main.c -I/usr/include/lua5.2 -llua -lm -ldl -pthreadentrará en un bucle infinito. Quiero controlar de alguna manera la variable lua y cambiarla a a=1, desde el programa principal para que salga del ciclo infinito. la razón para hacer tal prueba es que se asegurará de que antes de que salga el programa principal, este hilo salga primero controlando la variable lua. Sugiera cómo cambiar esta variable lua para que salga del ciclo while.
Interactuar con un estado lua en ejecución desde un subproceso diferente no es necesariamente seguro, por lo que modificar la variable global del script puede o no ser una idea útil dependiendo de dónde planee realizar ese cambio desde el lado C.
Si quisiera hacer esto, simplemente necesitaría usar la API lua Cap para establecer la variable global del nombre apropiado en el estado lua apropiado.
Una idea alternativa sería crear una función global should_exit que se llama al principio o al final de cada ciclo y cuando devuelve verdadero hace que el código lua se break o return . Esta función puede verificar cualquier cosa que quiera en el lado C de cualquier manera apropiada para el subproceso que se desee.
¿Por qué tener este bucle en Lua? En su lugar, puede hacer un bucle en c-thread, lua_pcall alguna función de punto de entrada (por ejemplo onEvent() ) en cada iteración.
Si el bucle tiene que estar en el script Lua, por ejemplo, en el caso de un esquema de configuración-bucle-limpieza, puede ejecutar el script en coroutine y usar coroutine.yield() como condición de bucle. El hilo debe lua_resume() con valor true o salir según la condición del lado c. (O reanude con false si se prefiere la limpieza del lado de Lua después del ciclo).
De todos modos, Lua no es seguro para subprocesos y no se puede llamar simultáneamente desde más de un subproceso.
Oh, fuiste muy duro en tu respuesta (sin embargo, seguro que fue un gran ejercicio). Las cosas podrían ser mucho más simples:
#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; }guión.lua:
print("Hi!") while shouldRun() do print("Running!") sleep(1) end print("Bye!")producción:
Hi! Running! Running! Running! Running! Running! Bye!Algunas cosas a tener en cuenta:
exit() . lua_close() recolectará basura todos los datos de usuario utilizados por el script, y su metamétodo __gc puede hacer algo útil como vaciar los búferes en el disco, etc. Pierde todas las posibilidades con una salida forzada.