【发布时间】:2013-10-08 04:50:24
【问题描述】:
我正在使用 cgo 包装一个 C 库并遇到了一组奇怪的链接器错误。我将问题归结为以下几点:
一个文件 header.h 包含
#ifndef HEADER_H
#define HEADER_H
#define CONSTANT1 ("")
#define CONSTANT2 ""
#define CONSTANT3 ((char*)0)
#define CONSTANT4 (char*)0
#endif /* HEADER_H */
并且 test.go 包含
package main
/*
#include "header.h"
*/
import "C"
func main() {
_ = C.CONSTANT1
_ = C.CONSTANT2
_ = C.CONSTANT3
_ = C.CONSTANT4
}
运行go run test.go 时出现以下错误:
# command-line-arguments
... _cgo_main.o:(.data.rel+0x0): undefined reference to `CONSTANT4'
... _cgo_main.o:(.data.rel+0x8): undefined reference to `CONSTANT3'
... _cgo_main.o:(.data.rel+0x10): undefined reference to `CONSTANT1'
collect2: ld returned 1 exit status
对此我有两个问题:
- 为什么链接器与预定义的常量有任何关系?
- 为什么
CONSTANT1、CONSTANT3、CONSTANT4显示为未定义,而不显示CONSTANT2?
提前致谢。
*编辑:定义为其他值(例如整数)的常量可以正常工作。
*Edit2:使用 go 版本 go1.1.2 linux/amd64
*Edit3:失败的完整示例:
我正在使用 C OpenLDAP 库并希望使用 LDAP_SASL_SIMPLE 常量。它在ldap.h 中定义为
#define LDAP_SASL_SIMPLE ((char*)0)
#define LDAP_SASL_NULL ("")
LDAP_SASL_NULL 常量给出了同样的错误。
一个最小的演示 go 程序:
package main
/*
#cgo LDFLAGS: -lldap
#include <ldap.h>
*/
import "C"
func main() {
_ = C.LDAP_SASL_SIMPLE
}
【问题讨论】:
-
疯狂猜测;如果正确:Go 希望通过 ABI(正确的链接)访问数据,使用符号名称。这不是预处理器宏所做的。 (我可能错了,因为我从未使用过 Go。)
-
@FUZxxl(现在猜猜谁在不了解这些语言的情况下解决了几个 Java、Python 和 Lua“问题”...:P)
-
嗯...我猜这是因为其他常量封装在大括号中或包含可能会使 cgo 混淆的强制转换。如果您能展示一个展示您的问题的最小完整示例,那就太好了。最好能链接到实际的库。
-
备案:我删除的评论(原来是第二条)写着:@H2CO3 你是对的。我把它删除了,因为我被OP的问题弄糊涂了,并质疑了自己。
-
您说其中一个常数有效,而另一个常数无效。哪一个起作用了?对于您提供的示例,我的原始示例适用。您需要在 Go 代码中重新定义常量。