CGo 不编译 C 文件

man*_*ior 0 go cgo go-build

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

测试.go

package main

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

func main() {
    C.helloWorld()
}
Run Code Online (Sandbox Code Playgroud)

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

我还尝试了go build test.go,这导致了相同的结果。最后,在CGo 不编译同一目录中的 C 文件之后,我只是执行了go build。这不起作用,因为我必须创建一个 .mod 文件(go build test.go)。然后,问题是PMDK.c中的三个函数(helloWorld和其他两个函数)据说被定义了多次。我无法让它构建我的更改。顺便说一句,如果我将源文件复制/移动到另一个目录并在那里构建它们,则更改将适用(仅一次,再次)。

tor*_*rek 5

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

package main

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

func main() {
    C.helloWorld()
}
Run Code Online (Sandbox Code Playgroud)

可以将 C 代码放入前缀中:

package main

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

...
Run Code Online (Sandbox Code Playgroud)

但是,如果您将 C 代码放入单独的文件中(prog.c等),则应该创建一个小的头文件来简单地声明每个函数,以及#include来自 C 代码和 Go 代码的头文件。1

跑步:

go build
Run Code Online (Sandbox Code Playgroud)

然后将编译 C 代码(如果已更改),并构建 Go 代码(如果已更改),并根据需要将两者链接在一起。如果您将#includeC 代码直接放入 Go 包中,就像您所做的那样,go build将构建 C 代码并构建包含 C 代码的Go 代码,这就是您获得重复定义的原因。

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


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

go build
Run Code Online (Sandbox Code Playgroud)

并且,C 代码将分别读取:

void func(int arg1, char *arg2);
Run Code Online (Sandbox Code Playgroud)

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