0

I am trying to wrap a C library in Golang. I am trying to call a C function in an already compiled library. I have both a .a file and a .so library file.

Where do I need to place the library files and how do i tell cgo that I am using these libraries?

I am rather a novice when it comes to C. Any help would be greatly appreciated.

Westy10101
  • 861
  • 2
  • 12
  • 25
  • Yes you can link to C libraries (that what cgo is mainly for). What problem are you having? – JimB Aug 31 '16 at 13:31
  • I want to call a client library but am unsure where to place the library so that I can reference it in go? And then how to tell go where the library is? – Westy10101 Aug 31 '16 at 13:34
  • There's a cgo directive specifically for pkg-config, `#cgo pkg-config`, and there's also `#cgo LDFLAGS`: https://golang.org/cmd/cgo/. You can use either of those to tell the linker how to find the libraries. – JimB Aug 31 '16 at 13:47
  • see this: http://stackoverflow.com/questions/37987643/how-to-link-golang-package-to-an-existing-c-project-using-go-from-c-on-windows –  Aug 31 '16 at 14:22
  • Thanks. Do you have an example? So if I have a library hello.a and put it in my go src in a folder called lib how do i set this up? – Westy10101 Aug 31 '16 at 14:55
  • @Westy10101: if you want to package the C library with your source, look for `{SRCDIR}` in the cgo documentation I linked. – JimB Aug 31 '16 at 15:13

1 Answers1

2

I'll explain it with this sample:

First build libhello.a using ./libs/m.c:

#include <stdint.h> 

extern uint64_t Add(uint64_t a, uint64_t b) {
    return a + b;
}

For this test sample libhello.a is inside ./libs/ :

m.go
└───libs
    m.c
    libhello.a

Then go build this m.go working sample:

package main

//#cgo LDFLAGS: -L${SRCDIR}/libs -lhello
//#include <stdint.h>
//extern uint64_t Add(uint64_t a, uint64_t b);
import "C"

import (
    "fmt"
)

func main() {
    fmt.Println(C.Add(C.uint64_t(10), C.uint64_t(20))) // 30
}

output:

30

When the cgo directives are parsed, any occurrence of the string ${SRCDIR} will be replaced by the absolute path to the directory containing the source file. This allows pre-compiled static libraries to be included in the package directory and linked properly. For example if package foo is in the directory /go/src/foo:

// #cgo LDFLAGS: -L${SRCDIR}/libs -lfoo

Will be expanded to:

// #cgo LDFLAGS: -L/go/src/foo/libs -lfoo
  • you can't use relative paths in LDFLAGS, because the build happens in a different directory than the source. That's why I mentioned `{SRCDIR}` above` – JimB Aug 31 '16 at 15:25
  • @JimB both `-L${SRCDIR}/libs` and `-L./libs` works here for me, so edited to general case: `-L${SRCDIR}/libs`. Thanks. –  Aug 31 '16 at 15:39
  • 1
    Thanks, literally you have just made my day! Sorry for being dim its been a fair few years since I have done any C. – Westy10101 Aug 31 '16 at 15:39
  • @Amd: it's probably because you're using `go build` with an assumed package of the current directory. You can't `go get` or `go install` with a relative path. – JimB Aug 31 '16 at 15:43