Pregunta

Tengo problemas para entender cómo usar las corrutinas correctamente con luabind.Hay una función con plantilla:

template<class Ret> 
Ret resume_function(object const& obj, ...)

Dónde (Ret) se supone que contiene los valores pasados ​​a yield por Lúa.

Mis puntos de confusión actuales son:

  • ¿Qué sucede si la función regresa en lugar de llamar? yield?Hace resume_function ¿Devolver el valor de retorno de la función?
  • ¿Cómo se supone que debes usar esta función si no sabes de antemano qué (o cuántos) parámetros se pasarán a yield?Por ejemplo, si hay varias funciones de rendimiento posibles, la función puede llamar.
  • ¿Cuál es el tipo de Ret si se pasan múltiples valores a yield?

¿Estoy completamente equivocado en cuanto a cómo funciona todo esto?Me imagino algo como esto.Del lado de Lua:

local img = loadImage("foo.png")

loadImage sería una función de C++ que solicita que la imagen se cargue en un hilo diferente y luego llama lua_yield, y algún tiempo después luabind::resume_function es llamado con img como parámetro.

¿Debería pasar? "foo.png" a yield como parámetro?A una función diferente antes de llamar yield, y luego nunca pasar ningún valor a yield?¿Cuál es la forma correcta de estructurar esto?Obviamente estoy entendiendo mal algo aquí.

¿Fue útil?

Solución

Donde se supone que (Ret) contiene los valores pasados ​​para generar por Lua.

Luabind solo admite valores de retorno únicos, por lo que solo devolverá el primer valor pasado a coroutine.yield.

¿Qué sucede si la función regresa en lugar de llamar a rendimiento?¿Resum_function devuelve el valor de retorno de la función?

Sí, obtienes su valor de retorno.

¿Cómo se supone que debes usar esta función si no sabes de antemano qué (o cuántos) parámetros se pasarán para producir?Por ejemplo, si hay varias funciones de rendimiento posibles, la función puede llamar.

Eso depende de usted;son tus funciones.Debe desarrollar convenciones sobre lo que las funciones resultantes reciben como parámetros y lo que proporciona la función que reanuda la rutina.

¿Cuál es el tipo de Ret si se pasan varios valores para producir?

Lo que quieras que sea.Es el parámetro de la plantilla.El número de parámetros de una función no influye en los valores de retorno que proporciona la función.

Recordar:Las funciones de Lua toman cualquier número de parámetros y pueden devolver cualquier cosa.Todo lo que Luabind puede hacer es pasar los parámetros que usted le proporcione y convertir el valor de retorno de las funciones de Lua en lo que espera que sea ese valor de retorno.Luabind, por supuesto, verificará el tipo de valor de retorno.Pero es su responsabilidad asegurarse de que las funciones que generan/devuelven devolverán algo que se pueda convertir al tipo que el usuario proporciona para Ret.

loadImage sería una función de C++ que solicita que la imagen se cargue en un hilo diferente y luego llama a lua_yield, y algún tiempo después se llama a luabind::resume_function con img como parámetro.

Si estás usando Luabind, nunca llames lua_yield directamente.La forma correcta de generar rendimiento en Luabind es agregar un atributo a una función que registre y que generará rendimiento cada vez que regrese de la función.La sintaxis es la siguiente:

module(L)
[
    def("do_thing_that_takes_time", &do_thing_that_takes_time, yield)
];

Es decir, una función C++ que produce debe siempre producir.Esta es una limitación de Luabind, al igual que con Lua normal, puedes elegir si ceder o no como mejor te parezca.

Además, no olvide que las corrutinas de Lua no son lo mismo que los subprocesos reales.No son preventivos;ellos van a solo ejecutar cuando usted explícitamente les dice que lo hagan con coroutine.resume o una llamada de currículum equivalente.

Además, deberías nunca ejecutar la misma instancia de Lua desde múltiples subprocesos C/C++;Lua no es seguro para subprocesos dentro de la misma instancia (lo que más o menos significa el mismo objeto lua_State).

Lo que parece querer hacer es que Lua llame a alguna función en C++ que a su vez genera un hilo para realizar algún proceso, luego hacer que el código Lua espere hasta que ese hilo se complete y luego reciba su respuesta.

Para hacer eso, necesita darle al script Lua un objeto que represente el hilo C++.Entonces tus loadImage la función no debe utilizar lógica de rutina;debería devolver un objeto que represente el hilo de C++.El script Lua puede preguntar al objeto si se ha completado y, si es así, puede consultar datos del mismo.

El lugar donde las corrutinas pueden entrar en juego aquí es si no desea que el script Lua espere hasta que finalice.Es decir, estás llamando al script Lua de vez en cuando, pero si el hilo de C++ no está terminado, entonces debería simplemente regresar.En cuyo caso, puedes hacer algo como esto:

function loadImageAsCoroutine(imageFilename)
    local cppThread = cpp.loadImage(imageFilename);

    local function threadFunc(cppThread)
        if(cppThread:isFinished()) then
            local data = cppThread:GetImage();
            return data;
        else
            coroutine.yield();
        end
    end

    local thread = coroutine.create(threadFunc);

    local errors, data = assert(coroutine.resume(thread, cppThread));

    if(coroutine.status(thread) == "dead") then
        return data;
    else
        return thread;
    end
end

Esta función devuelve una corrutina. o los datos de la imagen en sí.La persona que llama a esta función debe verificar el tipo;si el tipo es "hilo", entonces el hilo de C++ aún no ha terminado.De lo contrario, son los datos de la imagen.

La persona que llama a esta función puede bombear la rutina tanto como quiera con algún equivalente de coroutine.resume (ya sea luabind::resume_function o lo que sea).Cada vez, verifique el valor de retorno.Será nil si el hilo de C++ no ha terminado, y no nil de lo contrario.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top