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

如何在Go中调用CMake生成的C++静态库?解决未定义引用错误

Cgo链接C++静态库出现未定义引用的解决方案

问题背景

使用CMake 3.27构建C++静态库后,通过Go 1.20.7的cgo调用时,持续触发undefined reference to 'Adder'链接错误。此前尝试过SWIG和C包装层,其中C包装层在纯C程序中可正常工作,但在cgo环境下仍报错。环境为Ubuntu 20.04。

核心原因

C编译器会对函数名进行名字修饰(Name Mangling),生成包含函数参数类型等信息的特殊符号;而cgo默认通过GCC按C语言的符号规则查找函数,无法识别被修饰的C符号,导致链接失败。

解决步骤

1. 修改头文件,添加extern "C"声明

修改cpp.h,将函数声明包裹在extern "C"块中,同时兼容C/C++编译环境:

#ifndef CONNECT_H
#define CONNECT_H

#ifdef __cplusplus
extern "C" {
#endif

int Adder(int a, int b);

#ifdef __cplusplus
}
#endif

#endif

注意:原头文件中的宏connect易与系统函数重名,建议改为大写的CONNECT_H避免冲突。

2. 修正C++源文件的头引用

确保add.cpp中包含的是修改后的头文件(若原引用的ConnectionHeader.h是笔误,改为cpp.h):

#include "cpp.h"
#include <iostream>
using namespace std;

int Adder(int a, int b) {
    cout << a + b << " ";
    return a+b;
}

3. 重新编译C++静态库

用CMake重新构建库,确保生成的静态库中包含C风格的函数符号。可通过以下命令验证:

nm /home/omar/CMake_Projects/PROJECT_HEADER/build/libMyLibrary.a | grep Adder

若输出为T Adder(无多余修饰字符),说明符号已按C规则生成。

4. 验证Go代码调用

保持原Go代码不变,确保#cgo参数中的头文件路径(-I)和库路径(-L)正确指向实际文件位置:

package main

//#cgo CPPFLAGS: -I /home/omar/CMake_Projects/PROJECT_HEADER
//#cgo LDFLAGS: -L /home/omar/CMake_Projects/PROJECT_HEADER/build -l MyLibrary
//#include "cpp.h"
import (
    "C"
)
import "fmt"

func main() {
    a := C.int(9878)
    b := C.int(4)
    c := C.Adder(a, b)
    fmt.Println(c)
}

额外说明

若仍使用C包装层,需确保包装层的函数也通过extern "C"声明,且包装层代码用C编译器编译(或在C环境下按C规则编译),再与C库链接。直接给C++函数添加extern "C"是更简洁的解决方案。

内容的提问来源于stack exchange,提问作者Omar Khalil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 19:59:52