This package is based on the official Go plugin package, but modified to use any dynamic C libraries (Only Linux, FreeBSD, and macOS).
It provides a thread-safe interface for loading/unloading dynamic libraries, but the library symbols should be loaded manually using PluginInitializer.
go get github.com/Devoter/dlplugin
or use go mod tool.
WARNING: Windows implementation was not tested and should not be used.
This package uses cgo, it is highly recommended to read the official CGO documentation.
Open and prepare a plugin via dlplugin.Open() function:
Open(pathstring, initializerPluginInitializer) (*Plugin, error)It accepts a library filename and an initializer. The Init() method denotes a function type which initializes a plugin API.
typePluginInitializerinterface {
Init(lookupfunc(symNamestring) (uintptr, error)) error
}An opened library may be closed using the Close() method of the Plugin or the Close() function:
func (p*Plugin) Close() errorfuncClose(p*Plugin) errorAll examples have Makefiles, therefore you can build each example with the make command.
This example is a program that prints "Hello, world!" via dynamic library call. The example contains two implementations of program: naive and with an interface.
Plugin code
package main
import"C"import"fmt"//export printlnfuncprintln(v*C.char) {
s:=C.GoString(v)
fmt.Println(s)
}
funcmain() {}Program code
package main
/*#include <stdint.h>#include <stdlib.h>static void println(uintptr_t r, char *s){ ((void (*)(char *))r)(s);}*/import"C"import (
"flag""fmt""os""unsafe""github.com/Devoter/dlplugin"
)
typePluginAPIstruct {
Printlnfunc(sstring)
}
// Init initializes the plugin API.func (papi*PluginAPI) Init(lookupfunc(symNamestring) (uintptr, error)) error {
printlnPtr, err:=lookup("println")
iferr!=nil {
returnerr
}
papi.Println=func(sstring) {
cs:=C.CString(s)
deferC.free(unsafe.Pointer(cs))
C.println(C.uintptr_t(printlnPtr), cs)
}
returnnil
}
funcmain() {
pluginFilename:=flag.String("plugin", "", "plugin filename")
help:=flag.Bool("help", false, "show this text")
flag.Parse()
if*help {
flag.PrintDefaults()
return
}
varpapiPluginAPIplug, err:=dlplugin.Open(*pluginFilename, &papi)
iferr!=nil {
fmt.Fprintf(os.Stderr, "could not initialize a plugin by the reason: %v\n", err)
os.Exit(1)
}
deferplug.Close()
papi.Println("Hello, world!")
}See.
This example starts a random values generator from the library and reads generated values.
See.
This example concatenates two string with a dynamic library and returns the result via a callback function.
See.
This example loads two libs with the single interface. The program instanciates remote objects and works with them.