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

使用cgo编译Go代码失败:子目录C文件引发链接错误求助

Go cgo编译错误:子目录下C文件链接失败的原因与解决方法

环境信息

  • Go版本:go version go1.20.2 linux/amd64

项目结构

example/
├── main.go
└── lib/
    ├── lib.c
    └── lib.h

代码文件

main.go

package main

// #include "lib/lib.h"
// #include <stdio.h>
// #include <stdlib.h>
import "C"
import (
    "fmt"
    "unsafe"
)

func main() {
    cstrin := C.CString("welcome")
    s1 := C.struct_s1{b: cstrin, a: 100}

    C.f32_123(&s1)
    cs := C.GoString(s1.b)
    fmt.Println(cs)
    fmt.Println(s1)
    C.free(unsafe.Pointer(cstrin))
}

lib/lib.c

#include <stdlib.h>
#include <stdio.h>

void printc(char *str, int *t)
{
     str = "Test";
     printf("%d\n", *t);
     *t = 30;
     printf("%s\n", str);
}

void f32_123(struct s1 *s)
{
     printf("%s\n", s->b);
     s->a = 10;
     s->b = "Hello123";
     printf("%d\n", s->a);
     printf("%s\n", s->b);
}

lib/lib.h

struct s1 {
    int a;
    char *b;
};

void printc(char *str, int *t);
void f32_123(struct s1 *s);

编译错误信息

/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: /tmp/go-link-3024881602/000001.o: in function _cgo_cf24297edd23_Cfunc_f32_123': /tmp/go-build/cgo-gcc-prolog:49: undefined reference to f32_123'
collect2: error: ld returned 1 exit status

现象总结

  • 将所有文件放在同一目录(example)时,编译成功;
  • 将lib.c和lib.h放在子目录时,编译失败;
  • 在main.go中移除对f32_123的调用后,编译也能成功。

问题原因

cgo默认只会自动编译当前包目录下的C源文件,不会递归查找子目录里的.c文件。当lib.c放在子目录时,cgo未将其纳入编译流程,导致链接阶段找不到f32_123函数的实现,从而报错。

移除对f32_123的调用后,cgo不会生成该函数的调用代码,链接器无需查找对应符号,因此编译能通过。

解决方法

方法1:用#cgo LDFLAGS指定编译子目录C文件

在main.go的cgo注释块中添加编译指令,让cgo编译子目录下的lib.c:

package main

// #cgo LDFLAGS: ${SRCDIR}/lib/lib.c
// #include "lib/lib.h"
// #include <stdio.h>
// #include <stdlib.h>
import "C"
// 剩余代码不变

${SRCDIR}是cgo内置变量,代表当前Go文件所在目录,可正确定位子目录下的C文件。

方法2:将子目录C文件打包为静态库

  1. 进入lib目录生成静态库:
cd lib
gcc -c lib.c -o lib.o
ar rcs libmy.a lib.o
  1. 在main.go的cgo注释中链接该静态库:
package main

// #cgo LDFLAGS: ${SRCDIR}/lib/libmy.a
// #include "lib/lib.h"
// #include <stdio.h>
// #include <stdlib.h>
import "C"
// 剩余代码不变

此方式适合C代码较多的场景,便于管理。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:07:45