英文:
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 "pmdk.h"
*/
import "C"
func main() {
C.helloWorld()
}
You can put C code into the prefix:
package main
/*
#include <stdio.h>
void helloWorld() {
printf("hello world from C\n");
}
*/
import "C"
...
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 "fifth.h"
void func(int zorg, char *evil) {
// ...
}
and the C compiler will check that the declaration matches the definition.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论