使用Go 1.5的buildmode=c-archive,将net/http.Server与C链接。

huangapple go评论90阅读模式
英文:

Using Go 1.5 buildmode=c-archive with net/http.Server linked from C

问题

Go 1.5的即将发布将带来新的构建模式,允许将Go符号导出到C代码中进行链接和调用。我已经尝试了一些基本的“Hello world”示例,并成功运行,但是现在我正在尝试链接一个启动net/http.Server的Go库,但是失败了。代码如下(也可以在这里找到):

gohttplib.go:

package main

import "C"
import "net/http"

//export ListenAndServe
func ListenAndServe(caddr *C.char) {
    addr := C.GoString(caddr)
    http.ListenAndServe(addr, nil)
}

func main() {}

examples/c/main.c:

#include <stdio.h>
#include "../../gohttplib.h"

int main()
{
    ListenAndServe(":8000");
    return 0;
}

生成静态链接的对象和头文件没有问题:

$ go build -buildmode=c-archive

但是编译失败:

$ gcc -o gohttp-c examples/c/main.c gohttplib.a -lpthread
Undefined symbols for architecture x86_64:
  "_CFArrayGetCount", referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
  "_CFArrayGetValueAtIndex", referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
  "_CFDataAppendBytes", referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
  "_CFDataCreateMutable", referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
  "_CFDataGetBytePtr", referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
      __cgo_6dbb806e9976_Cfunc_CFDataGetBytePtr in gohttplib.a(000003.o)
     (maybe you meant: __cgo_6dbb806e9976_Cfunc_CFDataGetBytePtr)
  "_CFDataGetLength", referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
      __cgo_6dbb806e9976_Cfunc_CFDataGetLength in gohttplib.a(000003.o)
     (maybe you meant: __cgo_6dbb806e9976_Cfunc_CFDataGetLength)
  "_CFRelease", referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
      __cgo_6dbb806e9976_Cfunc_CFRelease in gohttplib.a(000003.o)
     (maybe you meant: __cgo_6dbb806e9976_Cfunc_CFRelease)
  "_SecKeychainItemExport", referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
  "_SecTrustCopyAnchorCertificates", referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
  "_kCFAllocatorDefault", referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [example-c] Error 1

这是在OS X 10.9.5上使用Go github存储库的最新版本(38e3427)进行的。我知道Go 1.5尚未发布,并且不能保证其正常工作,但我正在进行教育目的的尝试,我怀疑我可能遗漏了一些东西。

相关版本信息:

$ ld -v
@(#)PROGRAM:ld  PROJECT:ld64-241.9
configured to support archs: armv6 armv7 armv7s arm64 i386 x86_64 x86_64h armv6m armv7m armv7em
LTO support using: LLVM version 3.5svn
$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix
英文:

The upcoming release of Go 1.5 comes with new buildmodes which allow for exporting Go symbols to be linked and called from C code. I've been playing around with it and got basic "Hello world" examples working, but now I'm trying to link a Go library which starts a net/http.Server and it's failing. The code looks like this (it's also available here):

gohttplib.go:

package main

import &quot;C&quot;
import &quot;net/http&quot;

//export ListenAndServe
func ListenAndServe(caddr *C.char) {
	addr := C.GoString(caddr)
	http.ListenAndServe(addr, nil)
}

func main() {}

examples/c/main.c:

#include &lt;stdio.h&gt;
#include &quot;../../gohttplib.h&quot;

int main()
{
    ListenAndServe(&quot;:8000&quot;);
    return 0;
}

Producing the statically-linked object and headers works fine:

$ go build -buildmode=c-archive

But compiling against it is failing:

$ gcc -o gohttp-c examples/c/main.c gohttplib.a -lpthread
Undefined symbols for architecture x86_64:
  &quot;_CFArrayGetCount&quot;, referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
  &quot;_CFArrayGetValueAtIndex&quot;, referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
  &quot;_CFDataAppendBytes&quot;, referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
  &quot;_CFDataCreateMutable&quot;, referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
  &quot;_CFDataGetBytePtr&quot;, referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
      __cgo_6dbb806e9976_Cfunc_CFDataGetBytePtr in gohttplib.a(000003.o)
     (maybe you meant: __cgo_6dbb806e9976_Cfunc_CFDataGetBytePtr)
  &quot;_CFDataGetLength&quot;, referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
      __cgo_6dbb806e9976_Cfunc_CFDataGetLength in gohttplib.a(000003.o)
     (maybe you meant: __cgo_6dbb806e9976_Cfunc_CFDataGetLength)
  &quot;_CFRelease&quot;, referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
      __cgo_6dbb806e9976_Cfunc_CFRelease in gohttplib.a(000003.o)
     (maybe you meant: __cgo_6dbb806e9976_Cfunc_CFRelease)
  &quot;_SecKeychainItemExport&quot;, referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
  &quot;_SecTrustCopyAnchorCertificates&quot;, referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
  &quot;_kCFAllocatorDefault&quot;, referenced from:
      _FetchPEMRoots in gohttplib.a(000003.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [example-c] Error 1

This is using a recent version from the Go github repository (38e3427) on OS X 10.9.5. I understand that Go 1.5 is not released yet and that there are no guarantees about it working, but I'm doing this for educational purposes and I suspect I'm missing something.

Related versions:

$ ld -v
@(#)PROGRAM:ld  PROJECT:ld64-241.9
configured to support archs: armv6 armv7 armv7s arm64 i386 x86_64 x86_64h armv6m armv7m armv7em
LTO support using: LLVM version 3.5svn
$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix

答案1

得分: 8

原来这个问题存在于OSX/darwin上。为了解决这个问题,我们需要在gcc链接命令中添加-framework CoreFoundation -framework Security选项。最终的命令如下所示:

$ gcc -o gohttp-c examples/c/main.c gohttplib.a \
      -framework CoreFoundation -framework Security -lpthread

这个要求可能会在将来的Go版本中被移除。关于这个问题的更多讨论可以在这里找到:https://github.com/golang/go/issues/11258

英文:

Turns out this problem exists on OSX/darwin. To work around it, we need to add -framework CoreFoundation -framework Security options to the gcc linking command. The final command looks like this:

$ gcc -o gohttp-c examples/c/main.c gohttplib.a \
      -framework CoreFoundation -framework Security -lpthread

This requirement might be removed in a future version of Go. More discussion on this issue here: https://github.com/golang/go/issues/11258

huangapple
  • 本文由 发表于 2015年6月18日 00:09:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/30896892.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定