Golang中CGO调用外部C文件的方法与实践

Golang中CGO调用外部C文件的方法与实践 在cgo文档中,我找到这样一段话:“当Go工具发现一个或多个Go文件使用了特殊的import "C"时,它会在目录中查找其他非Go文件,并将它们作为Go包的一部分进行编译。任何……”

因此,我将我的C代码从Go文件的序言部分移到了一个外部的C文件中。

但是,当我执行“go run/build”时,它无法找到C文件中的函数。

我哪里做错了?或者我有什么没理解的地方?

先谢谢了。

5 回复

你是如何构建你的项目的?

更多关于Golang中CGO调用外部C文件的方法与实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


好的,没问题。

func main() {
    fmt.Println("hello world")
}

“go run main.go” 或 “go build main.go”,没什么特别的;这只是尝试在 Go 中使用 C 库(并且在前言部分工作得非常好),非常简单,代码行数非常少。

你必须构建整个包,例如在当前目录下使用 go build .。如果你只指定构建 main.go,那么只会得到 main.go

func main() {
    fmt.Println("hello world")
}

在CGO中调用外部C文件时,常见的问题是链接阶段未正确包含C源文件。根据你的描述,可能是构建过程中未自动包含外部C文件。以下是正确的实践方法:

首先,确保目录结构如下:

project/
├── main.go
└── foo.c

main.go中,使用import "C"并声明C函数,但不在序言中定义C代码:

package main

// #cgo CFLAGS: -I.
// #include "foo.h"
import "C"
import "fmt"

func main() {
    result := C.add(C.int(10), C.int(20))
    fmt.Printf("Result: %d\n", result)
}

创建对应的C头文件foo.h

#ifndef FOO_H
#define FOO_H

int add(int a, int b);

#endif

foo.c中实现函数:

#include "foo.h"

int add(int a, int b) {
    return a + b;
}

关键点:

  1. 确保C源文件与Go文件在同一目录下
  2. 使用#cgo指令指定编译选项(如-I.用于包含当前目录)
  3. 通过#include引入头文件

如果问题仍然存在,检查是否使用了模块模式。在模块模式下,可能需要将C文件放在模块根目录或使用//go:embed指令。也可以显式指定C文件:

// #cgo LDFLAGS: -L. -lfoo

对于更复杂的情况,可以使用cgo工具链:

go tool cgo main.go

这将生成中间文件,显示CGO如何处理C代码。如果C函数仍未找到,检查函数签名是否完全匹配,包括extern "C"声明(如果是C++代码)。

示例错误通常是未导出C函数。确保C函数使用C链接:

#ifdef __cplusplus
extern "C" {
#endif

int add(int a, int b);

#ifdef __cplusplus
}
#endif

最后,运行构建:

go build -x

-x标志显示详细构建过程,可以确认C文件是否被正确编译和链接。

回到顶部