golang build with gcc instead of g++ - go

I am trying to build Go that is calling c++ created .so (a.so) file on Linux, but I found that the go build . command always builds with gcc NOT g++. I already put the .cpp in the root directory instead in subdirectory.
Here is the output of go build command
client.go:90:10: could not determine kind of name for C.Init
cgo:
gcc errors for preamble:
In file included from client.go:8:
a.h:34:1: error: unknown type name 'class'
34 | class A {
| ^~~~~
a.h:34:11: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
34 | class A {
| ^ ^
Here is the client.go calling C code:
package main
// #cgo windows LDFLAGS: -la
// #cgo windows CXXFLAGS: -DWINDOWS
// #cgo linux LDFLAGS: -liba
// #cgo LDFLAGS: -L./libs
// #cgo CXXFLAGS: -I./
// #include "a.h"
import "C"
func function() {
handle, _ := dlOpen(PATH_TO_SO_FILE)
blob := C.Init(handle)
}
Here is the dlOpen related code, wrote in Go:
// +build linux
package main
// #cgo linux LDFLAGS: -ldl
// #include <dlfcn.h>
// #include <stdlib.h>
import "C"
import "errors"
import "unsafe"
type Handle {
c unsafe.Pointer
}
func dlOpen(filename string) (Handle, error) {
ptr := C.CString(filename)
defer C.free(unsafe.Pointer(ptr))
ret := C.dlopen(ptr, C.RTLD_LAZY)
if ret != nil {
return Handle{ret}, nil
}
return Handle{ret}, errors.New(C.GoString(C.dlerror()))
}
Here is the a.h
class A {
public:
Init(MHANDLE handle);
}

Your problem is not with the cpp file.
You wrote in the go file // #include "a.h".
Go currently compiles this as c and has no support for c++ and it looks like it will never have.
The only option you have is to make the header file valid in c.

Related

Load and call functions from a .so shared library [duplicate]

Is it possible to call a static object (.so) file from Go?
I've been searchign Google and I keep hitting upon the claim that I can do
lib, _ := syscall.LoadLibrary("...")
But trying this gives an error
undefined: syscall.LoadLibrary
and searching through Godocs I cannot find reference to this function in the syscall package.
Is it possible to load a library and call its functions?
On a POSIX platform, you could use cgo to call dlopen and friends:
// #cgo LDFLAGS: -ldl
// #include <dlfcn.h>
import "C"
import fmt
func foo() {
handle := C.dlopen(C.CString("libfoo.so"), C.RTLD_LAZY)
bar := C.dlsym(handle, C.CString("bar"))
fmt.Printf("bar is at %p\n", bar)
}
As #JimB said, you should just use CGO, and put the linking to the dynamic/static library there. as per this example:
// #cgo LDFLAGS: -lpng
// #include <png.h>
import "C"
...
var x:= C.png_whatever() // whatever the API is
Read more here: http://blog.golang.org/c-go-cgo
The answer by #Martin Törnwall explains how to use dlopen() for function lookup. Adding this answer to include sample code for how to actually call that function as well. (Using the approach suggested in the comments).
The idea is to write a wrapper function in C language for each function the shared library, which accepts a void* pointer (pointer to the function returned by dlopen()), converts it into an appropriate function pointer, and then call it.
Suppose we have a function named str_length in libfoo.so to calculate the length of a string, then the resulting Go code would be:
package main
import (
"fmt"
)
/*
#cgo LDFLAGS: -ldl
#include <dlfcn.h>
typedef int (*str_length_type)(char*); // function pointer type
int str_length(void* f, char* s) { // wrapper function
return ((str_length_type) f)(s);
}
*/
import "C"
func main() {
handle := C.dlopen(C.CString("libfoo.so"), C.RTLD_LAZY)
str_length_ptr := C.dlsym(handle, C.CString("str_length"))
result := C.str_length(str_length_ptr, C.CString("Hello World!"))
fmt.Println(result) // prints 12
}

gccgo-cross-compile can't compile cgo

I am trying to compile a simple go program using gccgo. My code uses cgo thou, gccgo couldn't compile it. This is my code (which compiles using go compiler):
package main
// #include <stdio.h>
// #include <stdlib.h>
//
// static void myprint(char* s) {
// printf("%s\n", s);
// }
import "C"
import "fmt"
func main(){
fmt.Println("Start")
cs := C.CString("Print from C")
C.myprint(cs)
fmt.Println("End")
}
when I compile the code using gccgo main.go -o gccoutput I get:
main.go:9:9: error: import file ‘C’ not found
import "C"
^
main.go:13:8: error: reference to undefined name ‘C’
cs := C.CString("Print from C")
^
main.go:14:2: error: reference to undefined name ‘C’
C.myprint(cs)
^
any ideas how to solve this?
EDIT:
I am trying to compile to ppc using the gccgo, and I don't want to use cross-compilation process of go compiler. I have tried to do (as suggested in the comments):
go build -compiler=gccgo
and it worked. Thou, when I do:
go build -comiler=powerpc-linux-gnu-gccgo main.go
I get:
invalid value "powerpc-linux-gnu-gccgo" for flag -compiler: unknown compiler "powerpc-linux-gnu-gccgo"
usage: go build [-o output] [-i] [build flags] [packages]
Run 'go help build' for details.

Define variable in cgo

I want, at build time, to define a string variable in cgo. None of the following approaches works.
#cgo CFLAGS: -DLOG="common"
'common' undeclared (first use in this function)
#cgo CFLAGS: -DLOG=common
'common' undeclared (first use in this function)
#cgo CFLAGS: -DLOG=\"common\"
malformed #cgo argument: -DLOG="common"
It appears this is not possible as cgo does some mangling/parsing -- can you get away with just a normal #define LOG "common" (i.e. not use the CGO special flags).
Or failing that You can invoke go run/go build like this: CGO_CFLAGS='-DLOG="common"' go run so.go
you could define a variable in cgo same as define it in c code,
example:
package main
/*
int initflag=2;
int GetInitFlag(){
return initflag;
}
*/
import "C"
import "fmt"
// CFlag get c flag
func CFlag() int {
value := C.GetInitFlag()
return int(value)
}
func main() {
fmt.Println(CFlag())
}
string type must convert char* in c to string
// C string to Go string
func C.GoString(*C.char) string
https://golang.org/cmd/cgo/

Calling functions in an so file from Go

Is it possible to call a static object (.so) file from Go?
I've been searchign Google and I keep hitting upon the claim that I can do
lib, _ := syscall.LoadLibrary("...")
But trying this gives an error
undefined: syscall.LoadLibrary
and searching through Godocs I cannot find reference to this function in the syscall package.
Is it possible to load a library and call its functions?
On a POSIX platform, you could use cgo to call dlopen and friends:
// #cgo LDFLAGS: -ldl
// #include <dlfcn.h>
import "C"
import fmt
func foo() {
handle := C.dlopen(C.CString("libfoo.so"), C.RTLD_LAZY)
bar := C.dlsym(handle, C.CString("bar"))
fmt.Printf("bar is at %p\n", bar)
}
As #JimB said, you should just use CGO, and put the linking to the dynamic/static library there. as per this example:
// #cgo LDFLAGS: -lpng
// #include <png.h>
import "C"
...
var x:= C.png_whatever() // whatever the API is
Read more here: http://blog.golang.org/c-go-cgo
The answer by #Martin Törnwall explains how to use dlopen() for function lookup. Adding this answer to include sample code for how to actually call that function as well. (Using the approach suggested in the comments).
The idea is to write a wrapper function in C language for each function the shared library, which accepts a void* pointer (pointer to the function returned by dlopen()), converts it into an appropriate function pointer, and then call it.
Suppose we have a function named str_length in libfoo.so to calculate the length of a string, then the resulting Go code would be:
package main
import (
"fmt"
)
/*
#cgo LDFLAGS: -ldl
#include <dlfcn.h>
typedef int (*str_length_type)(char*); // function pointer type
int str_length(void* f, char* s) { // wrapper function
return ((str_length_type) f)(s);
}
*/
import "C"
func main() {
handle := C.dlopen(C.CString("libfoo.so"), C.RTLD_LAZY)
str_length_ptr := C.dlsym(handle, C.CString("str_length"))
result := C.str_length(str_length_ptr, C.CString("Hello World!"))
fmt.Println(result) // prints 12
}

Linking Golang with XLib

I am trying to use XLib within Go using this code:
package main
// #cgo LDFLAGS: -lX11
// #include <X11/Xlib.h>
import (
"C"
"fmt"
)
func main() {
var dpy = C.XOpenDisplay(nil);
if dpy == nil {
panic("Can't open display")
}
fmt.Println("%ix%i", C.XDisplayWidth(), C.XDisplayHeight());
}
I'm compiling this via:
go tool cgo $(FILE)
But it results in the following error messages:
1: error: 'XOpenDisplay' undeclared (first use in this function)
1: note: each undeclared identifier is reported only once for each function it appears in
1: error: 'XDisplayWidth' undeclared (first use in this function)
1: error: 'XDisplayHeight' undeclared (first use in this function)
Any idea how to solve this?
cgo is picky about the formatting: you need to keep the "C" import separate, and place the preamble comments immediately above:
package main
// #cgo LDFLAGS: -lX11
// #include <X11/Xlib.h>
import "C"
import (
"fmt"
)
func main() {
var dpy = C.XOpenDisplay(nil)
if dpy == nil {
panic("Can't open display")
}
fmt.Println("%ix%i", C.XDisplayWidth(dpy, 0), C.XDisplayHeight(dpy, 0));
}
First of all, you do not want to use go tool cgo directly, unless you have specific reasons for doing so. Continue to use go build like you would for projects that do not use cgo.
Second, your cgo parameters need to be attached directly to the "C" import, so it has to read
// #cgo LDFLAGS: -lX11
// #include <X11/Xlib.h>
import "C"
import (
// your other imports
)

Resources