Reputation: 1325
I have a project where I would like to load Go plugins inside a C++ application.
After a lot of research, it is not clear for me whether or not Go supports this. I encountered a lot of discussions pointing out the bad habit of dynamic linking, proning IPC instead. Moreover it is not clear for me if dynamic linking is intended by the language or not (new Go philosophy ?).
cgo provides the ability to call C from Go or Go from C (inside Go), but not from plain old C. Or does it ?
Apparently something is going on upstream as well (https://codereview.appspot.com/7304104/)
main.c
extern void Print(void) __asm__ ("example.main.Print");
int main() {
Print();
}
print.go
package main
import "fmt"
func Print() {
fmt.Printf("hello, world\n")
}
Makefile :
all: print.o main.c
gcc main.c -L. -lprint -o main
print.o: print.go
gccgo -fno-split-stack -fgo-prefix=example -fPIC -c print.go -o print.o
gccgo -shared print.o -o libprint.so
Output :
/usr/lib/libgo.so.3: undefined reference to `main.main'
/usr/lib/libgo.so.3: undefined reference to `__go_init_main'
Is there a solution for that ? What is the best approach ? forking + IPC ?
References :
Upvotes: 3
Views: 2417
Reputation: 54079
I don't think you can embed Go into C. However you can embed C into Go and with a little stub C program you can call into C first thing which is the next best thing! Cgo definitely supports linking with shared libraries so maybe this approach will work for you.
Like this
main.go
// Stub go program to call cmain() in C
package main
// extern int cmain(void);
import "C"
func main() {
C.cmain()
}
main.c
#include <stdio.h>
// Defined in Go
extern void Print(void);
// C Main program
int cmain() {
printf("Hello from C\n");
Print();
}
print.go
package main
import "fmt"
import "C"
//export Print
func Print() {
fmt.Printf("Hello from Go\n")
}
Compile with go build
, and produces this output when you run it
Hello from C
Hello from Go
Upvotes: 7
Reputation: 91243
AFAIK, you cannot compile a Go package to a shared library witg 'gc' ATM, it may change in the future. There might be some chance with 'gccgo' as 'libgo' (Go runtime, I suppose) is a shared library already. I guess the missing piece is then only to properly initialize the runtime, which normally a Go command handles automatically.
The gccgo expert is I.L. Taylor, he is reachable at the golang-nuts mailing list almost daily. I suggest to ask him directly.
PS: Other problems possibly include the interaction of the Go garbage collector and the (C++) process memory etc. Maybe I'm too optimistic and it is not at all feasible.
Upvotes: 2