linux Debian Buster
go version go1.11.6 linux/amd64
gcc version 8.3.0 (Debian 8.3.0-6)
libmylib.go
package main
import "C"
import (
"fmt"
)
func say(text string) {
fmt.Println(text)
}
func main(){}
mylib.h
#ifndef MY_LIB_H
#define MY_LIB_H
#include <string>
void say(std::string text);
#endif
main.cpp
#include <string>
#include "mylib.h"
using namespace std;
int main() {
string text = "Hello, world!";
say(text);
return 0;
}
CGO_ENABLED=1 go build -o libmylib.so -buildmode=c-shared libmylib.go
g++ -L/path/to/lib/ -lmylib main.cpp -o my-test-program
/usr/bin/ld: /tmp/ccu4fXFB.o: in function 'main': main.cpp:(.text+0x53): undefined reference to `say(std::__cxx11::basic_string<char, std::char_traits, std::allocator >)'
collect2: error: ld returned 1 exit status
with change: package main -> package mylib
CGO_ENABLED=1 go build -o libmylib.so -buildmode=c-shared libmylib.go
-buildmode=c-shared requires exactly one main package
You have to use GoString
rather than std::string
in the C++ version. The error message you are getting is because of the type mismatch, manifesting as a link-time error.
See the cgo reference.
Here's a working example. There's a few differences from yours. The //export
directive is needed to include the function in the generated header file, the argument is *C.char
rather than string
or GoString
. The C++ code uses the header generated by cgo, and there has to be a const-removing cast from the static string (because go doesn't have C-like const).
package main
import "C"
import (
"fmt"
)
//export say
func say(text *C.char) {
fmt.Println(C.GoString(text))
}
func main() {}
#include "libmylib.h"
int main(void) {
say(const_cast<char*>("hello world"));
return 0;
}
This compiles to go file, generating libmylib.so
and libmylib.h
in the current directory.
go build -o libmylib.so -buildmode=c-shared libmylib.go
The compiles the C++ program, linking it to the shared library above:
g++ -L. main.cpp -lmylib -o hello_program
To run the program, LD_LIBRARY_PATH
needs to be set to the current directory. That would be different if program was installed and the shared library put in a sensible place.
LD_LIBRARY_PATH=. ./hello_program