3XX0
3XX0

Reputation: 1325

Go shared library as C++ plugin

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

Answers (2)

Nick Craig-Wood
Nick Craig-Wood

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

zzzz
zzzz

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

Related Questions