正确的Go类型传递给C函数?

I'm porting some server code I wrote in C over to Go and it uses an encryption library I really don't want to rewrite. Instead I'm trying to use Cgo to write a wrapper so that the rest of my code can call it more easily. Here's part of the header for the lib:

// encryption/encryption.h
#define CRYPT_BBCFG  1

typedef struct {
    // ...bunch of fields...
    uint32_t bb_posn; 
} CRYPT_SETUP;

int CRYPT_CreateKeys(CRYPT_SETUP* cs, void* key, unsigned char type);

And here's the proof-of-concept snippet I'm trying to get to work:

package goserv

//#include "encryption/encryption.h"
import "C"

func main() {
    cdata := new(C.struct_CRYPT_SETUP)
    key := make([]byte, 48)
    C.CRYPT_CreateKeys(cdata, &key, C.CRYPT_BLUEBURST)
}

I defined a test function (int test() { return 1; }) in the header and have no problem calling that from my code (via C.test()) nor referencing any of the #defined'd constants (C.CRYPT_BBCFG) but get the following error when I attempt to run go install goserv:

Undefined symbols for architecture x86_64:
  "_CRYPT_CreateKeys", referenced from:
   __cgo_e89359206bf1_Cfunc_CRYPT_CreateKeys in goserv.cgo2.o
       (maybe you meant: __cgo_e89359206bf1_Cfunc_CRYPT_CreateKeys)
ld: symbol(s) not found for architecture x86_64

At this point I'm assuming I'm just not calling the function with the correct arguments. I was under the impression that cdata is of type *C.struct_CRYPT_SETUP, key should be *byte (though it doesn't work without the & either) and C.CRYPT_BLUEBURST of type...something. Trying C.uchar(CRYPT_BLURBURST) also doesn't change anything.

Any suggestions on getting this code to compile?

Edit: Forgot my platform, I'm running Mac OS X 10.10

Edit2 (SOLVED): Jsor's point about using unsafe.Pointer with the address of the first element of key helped but I also had to move my C source files into the same directory as my Go file. There was another type error resulting from using C.struct_CRYPT_DATA instead of C.CRYPT_DATA, so if anyone else runs into errors like this:

./goserv.go:18: cannot use cdata (type *C.struct_CRYPT_SETUP) as type *C.struct___0 in argument to _Cfunc_CRYPT_CreateKeys

Then remove the struct_ prefix (though the cgo docs say that's how to directly reference C struct types)

You probably want &key[0], otherwise you're pointing to the Slice Header, which is a struct of 3 values. You end up getting a pointer to a pointer to your buffer, which is probably not what you want.

In general, the pointer to the backing buffer of a slice is &slice[0], not &slice.

As a standard disclaimer: be warned about passing Go-allocated buffers into C. Almost everybody does it, (including me) but it may not be a good idea, and may stop being supported at some point. It's probably fine as long as you keep a reference to the data for the entire duration it's in C, and don't store the pointer for later use on the C side, but it's plausible you'll end up with weirdness due to the Go 1.3 stack moving GC.

Update: Something I just remembered -- void* in C is analogous to Go's unsafe.Pointer. So your call should be:

C.CRYPT_CreateKeys(cdata, unsafe.Pointer(&key[0]), C.CRYPT_BLUEBURST)

Another issue may be if you usually link an external library with -l. For this, use

// #cgo LDFLAGS: -llibname

In the area right above import "C" where you do your includes.

Edit2: Also, looking at it more, it looks like the function CRYPT_CreateKeys is not defined in the header file -- only the function prototype. Make sure if it's defined in a separate .c file to declare it extern. Not doing so will trip up Go.

One more point if you are passing buffers in between go And C. It’s good option to write your C code in a way that, It copies buffer locally passed by GO. This will help when you are typecasting your buffer to Int* or some other pointer type. This way you will be independent of the buffer supplied By Cgo.