Debian Buster下Go与C++交互报错及包名修改后编译问题咨询
解决Go CGO生成共享库与C++链接的问题
让我们一步步拆解你遇到的两个问题,然后给出具体的解决方案:
问题1:C++链接时的undefined reference错误
这个错误的核心原因有两个:
- C++的名字修饰(Name Mangling):C++会对函数名进行特殊编码(比如你看到的
std::__cxx11::basic_string...),而Go通过CGO导出的是C风格的未修饰函数名,链接器无法匹配两者。 - 参数类型不兼容:Go的CGO只能导出兼容C语言的类型,
std::string是C++独有的类型,Go无法直接处理,自然也不会导出对应签名的函数。
问题2:修改package后的编译错误
-buildmode=c-shared是Go专门用来生成C/C++可调用的共享库的模式,它强制要求必须是main包——哪怕你的main函数是空的也没关系,因为Go工具链需要通过main包来生成共享库的初始化、导出表等必要结构。所以不能改成package mylib。
完整解决方案
1. 修改Go代码(libmylib.go)
保持package main,添加//export say注释告诉CGO要导出这个函数,同时使用C兼容的参数类型:
package main import "C" import ( "fmt" "unsafe" ) //export say func say(text *C.char) { // 将C字符串转换为Go字符串 goText := C.GoString(text) fmt.Println(goText) } func main() {} // 必须保留,c-shared模式要求
2. 修改C++头文件(mylib.h)
用extern "C"包裹函数声明,避免C++的名字修饰,同时改用C兼容的const char*作为参数:
#ifndef MY_LIB_H #define MY_LIB_H #ifdef __cplusplus extern "C" { #endif void say(const char* text); #ifdef __cplusplus } #endif #endif
3. 修改C++主程序(main.cpp)
调用时将std::string转换为C风格字符串(用c_str()方法):
#include <string> #include "mylib.h" using namespace std; int main() { string text = "Hello, world!"; say(text.c_str()); // 转换为const char* return 0; }
4. 重新编译
先编译Go共享库:
CGO_ENABLED=1 go build -o libmylib.so -buildmode=c-shared libmylib.go
然后编译C++程序(如果库在当前目录,用-L.指定库路径):
g++ -L. -lmylib main.cpp -o my-test-program
运行程序:
./my-test-program
你应该能看到输出Hello, world!。
内容的提问来源于stack exchange,提问作者LurkyDismal
相关产品推荐
相关产品推荐

