CGo无法编译C文件。

huangapple go评论85阅读模式
英文:

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 run test.go时,它只构建一次。无论我对PMDK.c做什么更改,我的程序每次都有完全相同的行为。

我还尝试了go build test.go,结果是一样的。
最后,按照CGo not compiling C files in same directory的建议,我只运行了go build。这并没有起作用,因为我必须创建一个.mod文件(go build test.go)。然后,问题是PMDK.c中的三个函数(helloWorld和其他两个)被认为是多次定义的。
我无法使其构建我的更改。
顺便说一下,如果我将源文件复制/移动到另一个目录并在那里构建它们,更改就会应用(再次只有一次)。

英文:

I have a really simple setup: A .go file (test.go) and a .c file (PMDK.c). I include the .c file in Go as follows:

test.go:

package main

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

func main() {
	C.helloWorld()
}

When I run go run test.go, it builds for exactly one time. Whatever changes I do to PMDK.c, my program has the exact same behavior every time.

I also tried go build test.go, which leads to the same result.
Finally , following CGo not compiling C files in same directory, I just did go build. This didn't work, since I had to create a .mod file (go build test.go). Then, the problem was that the three functions in PMDK.c (helloWorld and two others) were supposedly defined multiple times.
I can't make it build my changes.
By the way, if I copy/move the source files to another directory and build them there, the changes apply (only for once, again).

答案1

得分: 5

问题的核心是你的设置有问题:你的Go代码应该只在Cgo前缀中#include任何你想要单独编译的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等),你应该创建一个简单的头文件,只声明每个函数,并从C代码和Go代码中#include该头文件。1

运行:

go build

将编译C代码(如果有更改),并构建Go代码(如果有更改),并适当地将两者链接在一起。如果你直接将C代码#include到Go包中,就像你所做的那样,go build将同时构建C代码构建包含C代码的Go代码,这就是为什么会出现重复定义的原因。

你在Cgo头文件中嵌入的任何C代码都不应该出现在其他地方。如果你有一些现有的C代码基本上可以与Go一起工作,但需要一些调整,这是一个很好的地方放置小的“管道适配器”。


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

void func(int arg1, char *arg2);

然后,C代码将单独读取:

#include "fifth.h"

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

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

英文:

The heart of the problem is that your setup is wrong: your Go code should #include, in the Cgo prefix, only the headers for any C code you want compiled separately. For instance:

package main

/*
#include &quot;pmdk.h&quot;
*/
import &quot;C&quot;

func main() {
    C.helloWorld()
}

You can put C code into the prefix:

package main

/*
#include &lt;stdio.h&gt;
void helloWorld() {
        printf(&quot;hello world from C\n&quot;);
}
*/
import &quot;C&quot;

...

But if you put your C code into a separate file (prog.c, etc.), you should create a small header file that simply declares each function, and #include that header file from both the C code and the Go code.<sup>1</sup>

Running:

go build

will then compile the C code if it has changed, and build the Go code if it has changed, and link together the two as appropriate. If you #include the C code directly into the Go package, as you did, go build will both build the C code and build the Go code that includes the C code, which is why you get the duplicate definitions.

Whatever C code you embed in the Cgo header should appear nowhere else. This is a good place to put small "plumbing adapters", if you have some existing C code that mostly works with Go, but needs some tweaks.


<sup>1</sup>This is a general technique in C for making sure that the header file declarations of functions agree with the C source definition of the same functions. That is, the header fifth.h might say:

void func(int arg1, char *arg2);

and, separately, the C code will read:

#include &quot;fifth.h&quot;

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

and the C compiler will check that the declaration matches the definition.

huangapple
  • 本文由 发表于 2021年8月30日 19:05:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/68983066.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定