在C++中使用Go



linux Debian Buster

go版本go1.11.6 linux/am64

gcc版本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我的测试程序

/usr/bin/ld:/tmp/ccu4fXFB.o:在函数'main'中:main.cpp:(.text+0x53(:对"say(std::__cxx11::basic_string<char,std::char_traits,std:;allocater>("的未定义引用
collect2:错误:ld返回1个退出状态

更改:package main -> package mylib

CGO_ENABLED=1 go build-o libmylib.so-buildmode=c-shared libmylib.go

-buildmode=c-shared只需要一个主包

您必须在C++版本中使用GoString而不是std::string。您收到的错误消息是因为类型不匹配,表现为链接时间错误。

请参阅cgo参考资料。

下面是一个工作示例。和你的有一些不同。//export指令需要在生成的头文件中包含函数,参数是*C.char,而不是stringGoString。C++代码使用cgo生成的头,并且必须从静态字符串中移除const强制转换(因为go没有类似C的const(。

libmylib.go

package main
import "C"
import (
"fmt"
)
//export say
func say(text *C.char) {
fmt.Println(C.GoString(text))
}
func main() {}

main.cpp

#include "libmylib.h"
int main(void) {
say(const_cast<char*>("hello world"));
return 0;
}

命令

这将编译到go文件,在当前目录中生成libmylib.solibmylib.h

go build -o libmylib.so -buildmode=c-shared libmylib.go

编译C++程序,将其链接到上面的共享库:

g++ -L. main.cpp -lmylib -o hello_program

要运行程序,需要将LD_LIBRARY_PATH设置为当前目录。若安装了程序并将共享库放在一个合理的位置,那个就不一样了。

LD_LIBRARY_PATH=. ./hello_program
g++ -L/path/to/lib/ -lmylib main.cpp -o test

可能是错误的。阅读GCC文档的调用GCC章节g++的参数顺序非常重要

此外,测试(1(可以是一些现有的可执行文件。我建议用其他名字。

因此,考虑使用进行编译

g++ -Wall -g -O main.cpp -L/path/to/lib/ -lmylib -o my-test-program

您可能需要调试信息(-g(、警告(-Wall(和一些优化(-O(

你确实评论了

我需要在C++项目中使用Go文件中的一些函数。

这很奇怪。我认为您的操作系统是Linux。那么,你就不能在运行Go程序的进程和运行C++程序的另一个进程之间使用进程间通信设施吗?考虑在它们之间使用JSONRPC或HTTP。Go和C++中有几个开源库可以帮助您。

PS。正如我所评论的,从Go程序中调用C++代码可能会简单得多。当然,您确实需要阅读Go文档和关于cgo的博客,可能还需要阅读C++dlopen minihowto和一些C++参考资料。

最新更新