CGo 不编译 C 文件

CGo doesn't compile C files

我有一个非常简单的设置:一个 .go 文件 (test.go) 和一个 .c 文件 (PMDK.c).我在 Go 中包含 .c 文件如下:

test.go:

package main

/*
#include "PMDK.c"
#cgo pkg-config: libpmem
*/
import "C"

func main() {
    C.helloWorld()
}

当我 运行 go 运行 test.go 时,它只构建一次。无论我对 PMDK.c 做什么更改,我的程序每次都具有完全相同的行为。

我也尝试了 go build test.go,结果相同。 最后,在 之后,我只是 go build。这没有用,因为我必须创建一个 .mod 文件 (go build test.go)。然后,问题是 PMDK.c 中的三个函数(helloWorld 和其他两个)据说被定义了多次。 我无法让它构建我的更改。 顺便说一下,如果我 copy/move 将源文件放到另一个目录并在那里构建它们,则更改将应用​​(仅一次,再次)。

问题的核心是你的设置错误:你的Go代码应该#include,在Cgo前缀中,只有headers for 任何你想单独编译的 C 代码。例如:

package main

/*
#include "pmdk.h"
*/
import "C"

func main() {
    C.helloWorld()
}

可以将C代码放入前缀:

package main

/*
#include <stdio.h>
void helloWorld() {
        printf("hello world from C\n");
}
*/
import "C"

...

但是如果你把你的 C 代码放到一个单独的文件prog.c,等等),你应该创建一个小的header file 简单地声明了每个函数,#include 来自 C 代码和 Go 代码的 header 文件。1

运行:

go build

如果 C 代码发生变化,将编译它,如果发生变化,将构建 Go 代码,并且 link 将两者适当地结合在一起。如果您 #include 将 C 代码直接放入 Go 包中,就像您所做的那样,go build 将同时构建 C 代码 构建 Go 代码 ,其中包括 C 代码,这就是您得到重复定义的原因。

无论您在 Cgo header 中嵌入什么 C 代码,都不应出现在其他地方。这是放置小型“管道适配器”的好地方,如果您有一些现有的 C 代码主要适用于 Go,但需要一些调整。


1这是 C 中的通用技术,用于确保 header 文件 声明 函数与相同函数的 C 源代码定义。也就是说,header fifth.h 可能会说:

void func(int arg1, char *arg2);

另外,C 代码将显示为:

#include "fifth.h"

void func(int zorg, char *evil) {
    // ...
}

C 编译器将检查声明是否与定义匹配。