I need to write a golang plugin with a function that accepts an array of golang bytes, but when I try to call this function after loading the plugin in the client code, it always gives me
panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x40b22af]
Any suggestions on how to resolve this?
code to reproduce(highly simplified, but the same error occurs)
client.go
package main
import (
"plugin"
"log"
)
type T interface {
sayHi(data []byte)
}
func main() {
plgin, _ := plugin.Open("./plugin.so")
symbol, _ := plgin.Lookup("Endpoint")
b, _ := symbol.(T)
log.Println("From main")
data := []byte{1,2,3,4,5}
b.sayHi(data)
}
plugin.go(this program is built with buildmode=plugin
)
package main
import (
"log"
)
type dummy struct {}
func (d dummy)sayHi(data []byte) {
log.Println("From plugin")
log.Println(data)
}
var Endpoint dummy
func main() {
}
First, you should always check returned errors (and the result of type assertion from the plugin symbol)!
The problem in your case is that the sayHi()
method is unexported. So if you create an interface in your app, it will not match the unexported method created in the plugin.
Export the method, and it will work (given you don't get any other errors).
In the plugin:
func (d dummy) SayHi(data []byte) {
log.Println("From plugin")
log.Println(data)
}
In your main app:
type T interface {
SayHi(data []byte)
}
And when calling it:
b.SayHi(data)
One thing to note here. When you lookup a variable from a plugin, you get a pointer to the variable (else you could not change its value). For details, see: Plugin symbol as function return. What this means is that symbol
will be of type *dummy
, not dummy
. This doesn't cause any troubles here, as the method set of *dummy
also contains the SayHi()
method, just like the method set of dummy
, but you should not forget about this if you would attempt to type-assert a non-interface type (a concrete type) out of a plugin symbol.