cgo:体系结构x86_64的未定义符号

时间:2015-02-18 20:45:46

标签: go linker cgo

我想从C函数空间调用go func,但程序会抛出构建错误。

example.go

package main

/*
#include "test.c"
*/
import "C"
import "fmt"

func Example() {
    fmt.Println("this is go")
    fmt.Println(C.GoString(C.myprint(C.CString("go!!"))))
}

// export receiveC              (remove the extra space between // and export)
func receiveC(msg *C.char) {
    fmt.Println(C.GoString(msg))
}

func main() {
    Example()
}

test.c的

#include <stdio.h>

extern void receiveC(char *msg);

char* myprint(char *msg) {
    receiveC(msg);  // calling the exported go function
    return msg;     
    }

当我执行命令来运行/ build(go buildgo run example.gogo build example.go)程序时,它会抛出错误:

# github.com/subh007/goodl/cgo
Undefined symbols for architecture x86_64:
  "_receiveC", referenced from:
      _myprint in example.cgo2.o
      __cgo_6037ec60b2ba_Cfunc_myprint in example.cgo2.o
      _myprint in test.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

我正在跟随cgo slides编写程序。如果有任何错误,请告诉我。

Edit1:我使用的是OS-X 10.9操作系统。

EDIT2: 我在// export之间有一个额外的空格,//export之间不应有空格。但是现在我在构建时遇到以下错误:

# github.com/subh007/goodl/cgo
duplicate symbol _myprint in:
    $WORK/github.com/subh007/goodl/cgo/_obj/_cgo_export.o
    $WORK/github.com/subh007/goodl/cgo/_obj/example.cgo2.o
duplicate symbol _receiver_go in:
    $WORK/github.com/subh007/goodl/cgo/_obj/_cgo_export.o
    $WORK/github.com/subh007/goodl/cgo/_obj/example.cgo2.o
duplicate symbol _myprint in:
    $WORK/github.com/subh007/goodl/cgo/_obj/_cgo_export.o
    $WORK/github.com/subh007/goodl/cgo/_obj/test.o
duplicate symbol _receiver_go in:
    $WORK/github.com/subh007/goodl/cgo/_obj/_cgo_export.o
    $WORK/github.com/subh007/goodl/cgo/_obj/test.o
ld: 4 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

1 个答案:

答案 0 :(得分:4)

生成重复的符号,因为我已将test.c直接包含在go文件中。因此符号包括两次。

我认为,编写此代码的正确方法是(如果我错了请评论):

  1. 定义头文件(test.h):

    #ifndef TEST_H_
    #define TEST_H_
    
    char* myprint(char *msg);
    
    #endif
    
  2. 定义实现文件(test.c):

     #include <stdio.h>
     #include "test.h"
    
     extern void receiveC(char *msg);
    
     char* myprint(char *msg) {
         receiveC(msg);
         return msg;
      }
    
  3. .h文件包含在go文件中(example.go): 包主要

     /*
     #include "test.h"
     */
     import "C"
     import "fmt"
    
     func Example() {
          fmt.Println("this is go")
          fmt.Println(C.GoString(C.myprint(C.CString("go!!"))))
      }
    
      // make sure that there should be no space between the `//` and `export`
      //export receiveC
      func receiveC(msg *C.char) {
            fmt.Println(C.GoString(msg))
      }
    
      func main() {
           Example()
      }
    
  4. 构建程序:

     go build
    
  5. 运行生成的可执行文件(使用cgo名称生成可执行文件,需要一些调查才能找到原因)。

     $./cgo