API for plugins in Lua

I am implementing a plug-in system with Lua scripts for an application. Basically, this will allow users to extend functionality by defining one or more functions in Lua. The plugin function will be called in response to the application event.

Does Lua have some good open source plugins that can serve as models?

In particular, I am wondering what is the best way to pass parameters to a plugin and get return values ​​in a way that is flexible and easy to use for plugins.

To clarify, I'm interested in API design in terms of script programming in Lua, not in terms of hosting.

Any other advice or best practices related to plugin design in Lua will be appreciated.

+6
source share
2 answers

Lua's first-class features make such things so simple that I think you won't find much in your career. Remember that the Lua mantle should provide a minimal mechanism and allow individual programmers to design policies for themselves.

Your question is very general, but here is what I recommend for your API:

  • One plugin must be represented by one Lua table (just as a Lua module is represented by one table).

  • Table fields must contain table operations or callbacks.

  • General condition should not be stored in a table; it should be stored in local variables of the code that creates the table, for example,

    local initialized = false return { init = function(self, t) ... ; initialized = true end, something_else = function (self, t) if not initialized then error(...) end ... end, ... } 
  • You will also see that I recommend that all plugin operations use the same interface:

    • The first argument for the plugin is the table itself
    • Another argument is a table containing all the information needed for the operation.
    • Finally, each operation should return a table of results.

    The reason for passing and returning a single table instead of positional results is that it helps you maintain code compatibility as interfaces evolve.

In general, aggressively use tables and first-class functions , and protect the private state of the plugin .

+4
source

The plugin function will be called in response to the application event.

This indicates an observer pattern. For example, if your application has two events: "foo" and "bar", you can write something like:

 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 

Then, when the foo event occurs:

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

A client (e.g. a plugin) interested in the foo event would simply register a listener for it:

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

Expansion to suit your needs.

In particular, I am wondering what is the best way to pass parameters to the plugin and get return values

The plugin simply provides you with a function to call. You can pass any parameters you want and handle their return values, but you want to.

+2
source

Source: https://habr.com/ru/post/889402/


All Articles