dongyue8640 2013-10-01 21:21
浏览 153
已采纳

C常量的Cgo链接器错误

I'm using cgo to wrap a C library and have run into a strange set of linker errors. I've boiled the problem down to the following:

A file header.h contains

#ifndef HEADER_H
#define HEADER_H

#define CONSTANT1 ("")
#define CONSTANT2 ""
#define CONSTANT3 ((char*)0)
#define CONSTANT4 (char*)0

#endif /* HEADER_H */

And test.go contains

package main

/*
#include "header.h"
*/
import "C"

func main() {
    _ = C.CONSTANT1
    _ = C.CONSTANT2
    _ = C.CONSTANT3
    _ = C.CONSTANT4
}

Upon running go run test.go I get the following error:

# 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

I have two questions about this:

  1. Why does the linker have anything to do with pre-defined constants?
  2. Why do CONSTANT1, CONSTANT3, CONSTANT4 show up as undefined, but not CONSTANT2?

Thanks in advance.

*Edit: Constants defined as other values (e.g. ints) work fine.

*Edit2: Using go version go1.1.2 linux/amd64

*Edit3: A complete example of failure:

I'm working with the C OpenLDAP library and would like to use the LDAP_SASL_SIMPLE constant. It's defined in ldap.h as

#define LDAP_SASL_SIMPLE    ((char*)0)
#define LDAP_SASL_NULL      ("")

The LDAP_SASL_NULL constant gives the same error.

A minimal demonstrative go program:

package main

/*
#cgo LDFLAGS: -lldap

#include <ldap.h>
*/
import "C"

func main() {
    _ = C.LDAP_SASL_SIMPLE
}
  • 写回答

1条回答 默认 最新

  • doujing4555 2013-10-01 21:38
    关注

    I did originally answer something different based on how I thought cgo works. But if CONSTANT2 is recognized by cgo, something different might be the reason. Could you please:

    • run the tool nm on the library file and tell whether the output contains CONSTANT2 or any other constants you refer to that were at the same time established through #define. A library might declare a #define constant at the same time as a global symbol to get around compatibility issues.

    • provide a minimal working example of your problem if possible. This is, an example that can be compiled by someone who reads your post and exhibits your problem. Your question looks like it may miss some important parts to answer it. For instance, it would be nice to know the actual library you have problems with.


    original answer

    If you use #define, you do not establish anything the compiler will actually see. A #define is a preprocessing directive that is removed before parsing. To establish constants the compiler (and thus cgo) can see, actually declare them:

    const char *CONSTANT1 = "";
    const char *CONSTANT2 = "";
    const char *CONSTANT3 = (char*)0;
    const char *CONSTANT4 = (char*)0;
    

    If you cannot touch the header, there is typically not much you can do; you basically have to duplicate all constants in the Go part of your code:

    const (
         CONSTANT1 = "",
         CONSTANT2 = "",
         CONSTANT3 = nil,
         CONSTANT4 = nil,
     )
    

    You could try complex tricks like running cpp over your Go code, but this is likely to cause more trouble than it would solve problems.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器