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 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示
  • ¥15 arduino 步进电机
  • ¥20 程序进入HardFault_Handler
  • ¥15 关于#python#的问题:自动化测试