2022-07-07 04:32:00 +00:00
package main
import (
2023-02-19 19:27:25 +00:00
"plugin"
2022-07-07 04:32:00 +00:00
"hilbish/util"
rt "github.com/arnodel/golua/runtime"
)
2023-07-11 02:32:59 +00:00
// #interface module
// native module loading
2023-07-11 03:27:24 +00:00
// #field paths A list of paths to search when loading native modules. This is in the style of Lua search paths and will be used when requiring native modules. Example: `?.so;?/?.so`
2023-11-12 00:36:47 +00:00
/ *
The hilbish . module interface provides a function to load
2023-07-11 03:34:09 +00:00
Hilbish plugins / modules . Hilbish modules are Go - written
plugins ( see https : //pkg.go.dev/plugin) that are used to add functionality
to Hilbish that cannot be written in Lua for any reason .
2023-07-11 02:32:59 +00:00
2023-07-11 03:34:09 +00:00
Note that you don ' t ever need to use the load function that is here as
modules can be loaded with a ` require ` call like Lua C modules , and the
search paths can be changed with the ` paths ` property here .
To make a valid native module , the Go plugin has to export a Loader function
with a signature like so : ` func(*rt.Runtime) rt.Value ` .
2023-07-11 02:45:49 +00:00
2023-07-11 02:32:59 +00:00
` rt ` in this case refers to the Runtime type at
https : //pkg.go.dev/github.com/arnodel/golua@master/runtime#Runtime
2023-07-11 02:45:49 +00:00
2023-07-11 02:32:59 +00:00
Hilbish uses this package as its Lua runtime . You will need to read
it to use it for a native plugin .
2023-07-11 03:34:09 +00:00
Here is some code for an example plugin :
` ` ` go
package main
import (
rt "github.com/arnodel/golua/runtime"
)
func Loader ( rtm * rt . Runtime ) rt . Value {
return rt . StringValue ( "hello world!" )
}
` ` `
This can be compiled with ` go build -buildmode=plugin plugin.go ` .
If you attempt to require and print the result ( ` print(require 'plugin') ` ) , it will show "hello world!"
2023-07-11 02:32:59 +00:00
* /
2022-07-07 04:32:00 +00:00
func moduleLoader ( rtm * rt . Runtime ) * rt . Table {
exports := map [ string ] util . LuaExport {
"load" : { moduleLoad , 2 , false } ,
}
mod := rt . NewTable ( )
util . SetExports ( rtm , mod , exports )
return mod
}
2023-07-11 02:32:59 +00:00
// #interface module
// load(path)
// Loads a module at the designated `path`.
// It will throw if any error occurs.
2022-07-07 04:32:00 +00:00
func moduleLoad ( t * rt . Thread , c * rt . GoCont ) ( rt . Cont , error ) {
2023-02-19 19:27:25 +00:00
if err := c . CheckNArgs ( 1 ) ; err != nil {
2022-07-07 04:32:00 +00:00
return nil , err
}
path , err := c . StringArg ( 0 )
if err != nil {
return nil , err
}
2023-02-19 19:27:25 +00:00
p , err := plugin . Open ( path )
2022-07-07 04:32:00 +00:00
if err != nil {
return nil , err
}
2023-02-19 19:27:25 +00:00
value , err := p . Lookup ( "Loader" )
2022-07-07 04:32:00 +00:00
if err != nil {
return nil , err
}
2023-02-19 19:27:25 +00:00
loader , ok := value . ( func ( * rt . Runtime ) rt . Value )
2022-07-07 04:32:00 +00:00
if ! ok {
2023-02-19 19:27:25 +00:00
return nil , nil
2022-07-07 04:32:00 +00:00
}
2023-02-19 19:27:25 +00:00
val := loader ( t . Runtime )
2022-07-07 04:32:00 +00:00
return c . PushingNext1 ( t . Runtime , val ) , nil
}