Golang在Mac OS上使用CGO编译时出现x86_64架构的未定义符号问题
Golang在Mac OS上使用CGO编译时出现x86_64架构的未定义符号问题 main.go
package main
/*
#cgo CFLAGS: -g -Wall
#include <stdlib.h>
#include "greeter.h"
*/
import "C"
import (
"unsafe"
)
func main() {
name := C.CString("Gopher")
defer C.free(unsafe.Pointer(name))
year := C.int(2018)
C.greet(name, year)
}
greeter.h
#ifndef _GREETER_H
#define _GREETER_H
void greet(const char *name, int year);
#endif
greeter.c
#include "greeter.h"
#include <stdio.h>
void greet(const char *name, int year) {
printf("Greetings, %s from %d! We come in peace :)", name, year);
}
命令 $ go build -buildmode=c-archive -o greeter.a main.go
//输出
# command-line-arguments
Undefined symbols for architecture x86_64:
"_greet", referenced from:
__cgo_4d6b7d3a5d3b_Cfunc_greet in _x002.o
(maybe you meant: __cgo_4d6b7d3a5d3b_Cfunc_greet)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
你解决过这个问题吗?能给我一些建议吗? 谢谢,
更多关于Golang在Mac OS上使用CGO编译时出现x86_64架构的未定义符号问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
$ ls
greeter.c greeter.h main.go
$ go build -buildmode=c-archive -o greeter.a
$ ls
greeter.a greeter.c greeter.h main.go
$```更多关于Golang在Mac OS上使用CGO编译时出现x86_64架构的未定义符号问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这个问题是由于链接器找不到greet函数的实现导致的。在构建过程中,Go工具链没有将greeter.c文件包含在编译过程中。正确的做法是将C源文件与Go文件一起编译。
以下是修改后的main.go文件,通过#cgo指令指定需要编译的C源文件:
package main
/*
#cgo CFLAGS: -g -Wall
#include <stdlib.h>
#include "greeter.h"
*/
import "C"
import (
"unsafe"
)
func main() {
name := C.CString("Gopher")
defer C.free(unsafe.Pointer(name))
year := C.int(2018)
C.greet(name, year)
}
同时,需要修改构建命令,确保C源文件被正确包含。以下是几种解决方案:
方案1:使用cgo指令指定C源文件
在main.go文件中添加greeter.c的引用:
package main
/*
#cgo CFLAGS: -g -Wall
#include <stdlib.h>
#include "greeter.h"
void greet(const char *name, int year);
*/
import "C"
import (
"unsafe"
)
func main() {
name := C.CString("Gopher")
defer C.free(unsafe.Pointer(name))
year := C.int(2018)
C.greet(name, year)
}
方案2:修改构建命令
将C源文件作为参数传递给go build命令:
$ go build -buildmode=c-archive -o greeter.a main.go greeter.c
方案3:创建独立的C共享库 首先编译C代码为动态库:
$ gcc -c -fPIC -o greeter.o greeter.c
$ gcc -shared -o libgreeter.dylib greeter.o
然后在Go文件中指定链接参数:
package main
/*
#cgo CFLAGS: -g -Wall
#cgo LDFLAGS: -L. -lgreeter
#include <stdlib.h>
#include "greeter.h"
*/
import "C"
import (
"unsafe"
)
func main() {
name := C.CString("Gopher")
defer C.free(unsafe.Pointer(name))
year := C.int(2018)
C.greet(name, year)
}
构建Go程序:
$ go build -o main main.go
方案4:使用//go:embed指令(Go 1.16+)
如果使用Go 1.16或更高版本,可以嵌入C源文件:
package main
/*
#cgo CFLAGS: -g -Wall
#include <stdlib.h>
#include "greeter.h"
*/
import "C"
import (
_ "embed"
"unsafe"
)
//go:embed greeter.c
var greeterSource string
func main() {
name := C.CString("Gopher")
defer C.free(unsafe.Pointer(name))
year := C.int(2018)
C.greet(name, year)
}
对于你的具体错误,最直接的解决方案是方案2,在构建命令中包含C源文件:
$ go build -buildmode=c-archive -o greeter.a main.go greeter.c
这样Go工具链会将greeter.c文件与Go代码一起编译,确保greet函数的实现被正确链接到最终的静态库中。

