Reputation: 7829
I'm still on the learning curve with Go, but I've managed to compile and run a Go program that includes a C object file. The objective is to call an existing static C++ library. The call will be a bit like a command line invocation - so a simple C wrapper function is perfectly acceptable, and arguably simpler. Unfortunately, I cannot get Go to recognize this wrapper!
I've simplified my code to the following...
package main
// #cgo CFLAGS: -I. -g -Wall
// #cgo LDFLAGS: -L. -lSMHeatmapLib
// #include <stdlib.h>
// #include "ExternalJSON.h"
import "C"
import (
"fmt"
"unsafe"
)
const MAX_RETURN_BUFFER int = 8192
func main() {
var result_str string;
in_json := "The cat sat on the mat"
in_buff := C.CString(in_json)
defer C.free(unsafe.Pointer(in_buff))
in_sz := C.int( len(in_json) )
out_buff := C.malloc( C.sizeof_char * MAX_RETURN_BUFFER )
defer C.free(unsafe.Pointer(out_buff) )
sz := C.RunWithJSON(in_buff,in_sz, (*C.char)(out_buff),MAX_RETURN_BUFFER);
b:= C.GoBytes(out_buff,sz)
result_str = string(b)
fmt.Printf("Return: >%s<\n", result_str)
}
ExternalJSON.h is as follows:
int RunWithJSON( char* in, int in_len, char* out, int max_out);
And ExternalJSON.c:
#include "ExternalJSON.h"
int RunWithJSON( char* in, int in_len, char* out, int max_out)
{
for (int i=0; i<in_len; i++)
{
out[in_len-1-i] = in[i];
}
int olen = in_len;
// and add a marker on the end
out[olen++] = '#';
out[olen++] = '\0';
return olen;
}
(ie. just a simple test at the moment: String in, String out. As you can guess we'll be working with JSON later) This is built with gcc. (the rest of the library is C++ and uses g++) For the final link I use:
ar rcs $(TARGET) $(OBJS)
To remove the potential for any path issues, I copy the static library and ExternalJSON.h to the same directory as main.go .
Building with go build
, the result is:
# _/my/path/main
/usr/bin/ld: $WORK/b001/_x002.o: in function `_cgo_750343fded39_Cfunc_RunWithJSON':
/tmp/go-build/cgo-gcc-prolog:58: undefined reference to `RunWithJSON'
collect2: error: ld returned 1 exit status
Why can't go see the function definition in the library?
Yes I saw: How do you statically link a c library in go using cgo? but the suggested command line invocation of go build did not work either.
Upvotes: 2
Views: 88
Reputation: 7829
Yes the function was being compiled as a C++ name, even though it was entirely C with no object references.
There are two solutions:
Compile the code as pure C using gcc instead of g++. The file has to be pure C though, and the intention is to use it as an interface to the underlying C++ library.
Use extern "C", eg:
extern "C" { int myFunction (char* wibble) { // Do stuff with C++ } }
This lets you compile the source file as C++ (essential if you're going to use objects), but everything in the extern "C" { } (eg. the wrapper function myFunction
) is still accessible externally from Go.
Upvotes: 0