2

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.

4
  • 2
    When you build ExternalJSON.c and run ar, what library are you producing? Are you placing it into SMHeatmapLib.a? If so, does nm SMHeatmapLib.a successfully show RunWithJSON? Commented Feb 27 at 0:08
  • grepping nm gives the line: 0000000000000000 T _Z11RunWithJSONPciS_i Commented Feb 27 at 1:00
  • 2
    Are you sure that you're compiling it as C, not C++? That looks like a C++-mangled name. One could suggest throwing an extern "C" on, but that may just cover up the fundamental issue (if you're really intending to compile as C, not C++. If your goal is to build it as C++, yes, extern "C" is what you'd want.). Commented Feb 27 at 1:07
  • @CarsonHoffman Yep that is it - thanks! Using a local copy (to ensure I didn't have any path issues) specifically. I did have it working with a path, so it should be easy enough to go back and use the correct one. I'll consider extern "C" - it would make the library Makefile a little simpler. (there was also an issue with my const - but that was just a Go newbie casting issue :-) ) Commented Feb 27 at 2:21

1 Answer 1

0

Yes the function was being compiled as a C++ name, even though it was entirely C with no object references.

There are two solutions:

  1. 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.

  2. 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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.