2011-05-30 11 views
6

Estoy implementando un sistema de complemento con scripts Lua para una aplicación. Básicamente, permitirá a los usuarios ampliar la funcionalidad definiendo una o más funciones en Lua. Se llamará a la función de complemento en respuesta a un evento de aplicación.API para el marco de plugin en Lua

¿Existen algunos buenos frameworks de complemento de código abierto en Lua que puedan servir como modelo?

En particular, me pregunto cuál es la mejor manera de pasar parámetros al plugin y recibir los valores devueltos, de una manera que sea flexible y fácil de usar para los escritores de plugins.

Solo para aclarar, estoy interesado en el diseño de la API desde el punto de vista de la programación de scripts en Lua, no desde el punto de vista de la aplicación de alojamiento.

Cualquier otro consejo o mejores prácticas relacionadas con el diseño de un sistema de complemento en Lua será apreciado.

Respuesta

4

Las funciones de primera clase de Lua hacen que este tipo de cosas sean tan simples que creo que no encontrará mucho en el camino de los marcos. Recuerde que el mantra de Lua es proporcionar un mecanismo mínimo y dejar que los programadores individuales elaboren la política por sí mismos.

Su pregunta es muy general, pero aquí es lo que recomiendo para su API:

  • Un único plug-in debe estar representado por una única tabla Lua (al igual que un módulo Lua está representado por una sola tabla) .

  • Los campos de la tabla deben contener operaciones o devoluciones de llamada de la tabla.

  • Estado compartido debería no almacenarse en la tabla; se debe almacenar en variables locales del código que crea la tabla, por ejemplo,

    local initialized = false 
    
    return { 
        init = function(self, t) ... ; initialized = true end, 
        something_else = function (self, t) 
             if not initialized then error(...) end 
             ... 
            end, 
        ... 
    } 
    
  • También verá que recomiendo todas las operaciones de plugins utilizan la misma interfaz:

    1. El primer argumento al complemento es la tabla en sí
    2. El único otro argumento es una tabla que contiene toda la demás información que necesita la operación.
    3. Finalmente, cada operación debe devolver una tabla de resultados.

    El motivo de pasar y devolver una sola tabla en lugar de resultados posicionales es que lo ayudará a mantener el código compatible a medida que evolucionan las interfaces.

En resumen, tablas de destino y funciones de primera clase agresivamente y proteger estado privado de su plugin.

+1

Una interfaz más simple puede ser más fácil para los scripters. Por ejemplo, solo requiere que los scripters proporcionen funciones 'enter',' exit' y 'walk'. Use los valores predeterminados para las funciones que no se proporcionan. Establezca un entorno apropiado después de cargar cada script, antes de ejecutarlos. – lhf

+0

Gracias Norman. Fue una pregunta muy general, pero tu respuesta es lo que estaba buscando. – alexrs

+0

@lhf También creo que una interfaz más simple sería más fácil para los usuarios. Tomaré el consejo sobre pasar argumentos como tablas, pero haré que los usuarios simplemente definan algunas funciones y configuren una operación no operativa predeterminada. Por cierto, gracias por Lua, excelente trabajo. :) – alexrs

2

Se llamará a la función de complemento en respuesta a un evento de aplicación.

Eso sugiere el patrón de observador.Por ejemplo, si su aplicación tiene dos eventos, 'foo' y 'bar', se podría escribir algo como:

HostApp.listeners = { 
    foo = {}, 
    bar = {}, 
} 
function HostApp:addListener(event, listener) 
    table.insert(self.listeners[event], listener) 
end 
function HostApp:notifyListeners(event, ...) 
    for _,listener in pairs(self.listeners[event]) do 
     listener(...) 
    end 
end 

Luego, cuando el evento foo sucede:

self:notifyListeners('foo', 'apple', 'donut') 

un cliente (por ejemplo, una plug-in) interesados ​​en el evento foo acaba de registrar un detector para ello:

HostApp:addListener('foo', function(...) 
    print('foo happened!', ...) 
end) 

Extender para satisfacer sus necesidades.

En particular, me pregunto cuál es la mejor manera de pasar parámetros al plugin y recibir los valores devueltos

El plugin sólo te supples una función para llamar. Puede pasar los parámetros que desee y procesar sus valores de retorno como lo desee.