tl;dr: - Linux debugging works - macOS running works, debugging doesn't.
85 lines
2 KiB
Go
85 lines
2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"math/rand"
|
|
"path/filepath"
|
|
"plugin"
|
|
|
|
"code.osinet.fr/fgm/go_plugin_demo"
|
|
)
|
|
|
|
func loadPlugins(names []string) (map[string]*plugin.Plugin, error) {
|
|
plugins := make(map[string]*plugin.Plugin)
|
|
for _, name := range names {
|
|
plug, err := plugin.Open(filepath.Join("plugins", name, name+".so"))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed opening plugin %q: %w", name, err)
|
|
}
|
|
plugins[name] = plug
|
|
}
|
|
return plugins, nil
|
|
}
|
|
|
|
/*
|
|
Name obtains the name of a plugin.
|
|
*/
|
|
func Name(p *plugin.Plugin) (string, error) {
|
|
const symbolName = "InternalName"
|
|
var nameSymbol plugin.Symbol
|
|
|
|
nameSymbol, err := p.Lookup(symbolName)
|
|
if err != nil {
|
|
return "", fmt.Errorf("could not find %q in plugin %q: %w",
|
|
symbolName, nameSymbol, err)
|
|
}
|
|
pName, ok := nameSymbol.(*string)
|
|
if !ok {
|
|
return "", fmt.Errorf(`symbol %q was not a string`, symbolName)
|
|
}
|
|
return *pName, nil
|
|
|
|
}
|
|
|
|
func Work(p *plugin.Plugin, n uint) (string, error) {
|
|
const symbolWork = "Work"
|
|
var workSymbol plugin.Symbol
|
|
|
|
workSymbol, err := p.Lookup(symbolWork)
|
|
if err != nil {
|
|
return "", fmt.Errorf("could not find %q in plugin %q: %w",
|
|
symbolWork, workSymbol, err)
|
|
}
|
|
work, ok := workSymbol.(*go_plugin_demo.Worker)
|
|
if !ok {
|
|
return "", fmt.Errorf(`symbol %q was not a Worker`, symbolWork)
|
|
}
|
|
res := (*work)(n)
|
|
return res, err
|
|
}
|
|
|
|
func main() {
|
|
names := []string{"foo", "bar"}
|
|
plugins, err := loadPlugins(names)
|
|
if err != nil {
|
|
log.Fatalf("failed loading plugins: %v", err)
|
|
}
|
|
|
|
for range 10 {
|
|
for name, plug := range plugins {
|
|
quantity := uint(rand.Intn(4))
|
|
internalName, err := Name(plug)
|
|
if err != nil {
|
|
log.Fatalf("Failed getting internal name for plugin %q: %v", name, err)
|
|
}
|
|
fmt.Printf("Sending %d units of work to %s\t", quantity, internalName)
|
|
res, err := Work(plug, quantity)
|
|
if err != nil {
|
|
log.Fatalf("Failed getting %d units of work from plugin %q: %v",
|
|
quantity, name, err)
|
|
}
|
|
fmt.Printf("Result from %q: %q\n", internalName, res)
|
|
}
|
|
}
|
|
}
|