You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Debian Buster下Go与C++交互报错及包名修改后编译问题咨询

解决Go CGO生成共享库与C++链接的问题

让我们一步步拆解你遇到的两个问题,然后给出具体的解决方案:

问题1:C++链接时的undefined reference错误

这个错误的核心原因有两个:

  1. C++的名字修饰(Name Mangling):C++会对函数名进行特殊编码(比如你看到的std::__cxx11::basic_string...),而Go通过CGO导出的是C风格的未修饰函数名,链接器无法匹配两者。
  2. 参数类型不兼容: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 15:22:49