简单的 CGO 示例编译失败并出现 "duplicate symbol" 错误
Simple CGO example fails compilation with "duplicate symbol" error
我想用 CGO 做一个从 Go 调用 C 代码的简单例子。但由于某种原因,我无法达到预期。编译失败并出现以下错误:
go build main.go
# awesomeProject1/print
duplicate symbol '_do_print' in:
$WORK/b002/_x002.o
$WORK/b002/_x003.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
代码:
// print/print.c
#include <stdio.h>
void do_print(char * x){
printf("%s", x);
}
// print/print.go
package print
// #include <print.c>
import "C"
func DoPrint() {
C.do_print(C.CString("Hello!"))
}
// main.go
package main
import "awesomeProject1/print"
func main() {
print.DoPrint()
}
如果我将 do_print
函数设为静态,它会编译,但我无法为稍后要集成的第 3 方代码执行此操作。
我是否遗漏了文档中的一些重要部分?教程都是相似的,并声称在我的示例失败的地方工作。请帮忙!
转到版本 1.16.4
这里发生了两件事:
go build
编译 *.c
除了 *.go
1
#include <print.c>
完全等同于用 print.c
的内容覆盖 include 语句
因此,您正在编译print.c
的内容两次:一次是CC编译print.c
,一次是CGo编译print.go
。因此,print.c
和 print.go
的目标文件都包含在 print.c
中定义的所有导出符号。所以你得到了两份 do_print
。将 do_print
设为静态是可行的,因为声明为 static
的函数不会被 CC 导出。
包含 .c
文件(例如 #include <file.c>
)几乎总是一个坏主意。 如果您有正当理由 #include
函数体,约定是使用头文件(.h
)。这就是 C++ 模板库所做的(比如 Boost、IIRC)。因为C文件通常不包含,而H文件通常包含,包含C文件颠覆了预期,因此很可能导致混乱和问题.
1 IIRC,如果包中的任何 Go 文件导入 "C"
,Go 将编译包中的 C 文件。也就是说,如果一个包中没有任何 Go 文件使用 CGo,Go 将忽略该包中的 C 文件。
我想用 CGO 做一个从 Go 调用 C 代码的简单例子。但由于某种原因,我无法达到预期。编译失败并出现以下错误:
go build main.go
# awesomeProject1/print
duplicate symbol '_do_print' in:
$WORK/b002/_x002.o
$WORK/b002/_x003.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
代码:
// print/print.c
#include <stdio.h>
void do_print(char * x){
printf("%s", x);
}
// print/print.go
package print
// #include <print.c>
import "C"
func DoPrint() {
C.do_print(C.CString("Hello!"))
}
// main.go
package main
import "awesomeProject1/print"
func main() {
print.DoPrint()
}
如果我将 do_print
函数设为静态,它会编译,但我无法为稍后要集成的第 3 方代码执行此操作。
我是否遗漏了文档中的一些重要部分?教程都是相似的,并声称在我的示例失败的地方工作。请帮忙!
转到版本 1.16.4
这里发生了两件事:
go build
编译*.c
除了*.go
1#include <print.c>
完全等同于用print.c
的内容覆盖 include 语句
因此,您正在编译print.c
的内容两次:一次是CC编译print.c
,一次是CGo编译print.go
。因此,print.c
和 print.go
的目标文件都包含在 print.c
中定义的所有导出符号。所以你得到了两份 do_print
。将 do_print
设为静态是可行的,因为声明为 static
的函数不会被 CC 导出。
包含 .c
文件(例如 #include <file.c>
)几乎总是一个坏主意。 如果您有正当理由 #include
函数体,约定是使用头文件(.h
)。这就是 C++ 模板库所做的(比如 Boost、IIRC)。因为C文件通常不包含,而H文件通常包含,包含C文件颠覆了预期,因此很可能导致混乱和问题.
1 IIRC,如果包中的任何 Go 文件导入 "C"
,Go 将编译包中的 C 文件。也就是说,如果一个包中没有任何 Go 文件使用 CGo,Go 将忽略该包中的 C 文件。