gccgo-cross-compile can't compile cgo - go

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.

Related

CGO did not generate header file at Mac OS

I run the below code at Win 10 and got both lib and lib.h generated, tried the same at Mac but only lib got generated, and the lib.h not appeared!!
// file: lib/go.mod
module hasan/lib
go 1.14
And
// file: lib/main.go
package main
import "fmt"
//export HelloWorld
func HelloWorld() {
fmt.Printf("hello world")
}
func main() {}
And made the build as:
$ go build -buildmode=c-shared
No error show up
Th error was due to missing:
import "C"
In the lib/main.go this is the one responsible about generating the proper header file lib.h
Example
Create go file lib.go
package main
import "C"
import "fmt"
//export HelloWorld
func HelloWorld() {
fmt.Printf("hello world from GO\n")
}
func main() {}
Compile the above as:
go build -o lib.so -buildmode=c-shared lib.go
Then app.c as:
#include<stdio.h>
#include "lib.h"
int main(){
HelloWorld();
printf("Hello from c\n");
return 0;
}
And compile it (and build executable) as:
cc -o output app.c lib.so
And call the output as:
Hasans-Air:Documents hajsf$ ./output
hello world from GO
Hello from c

golang build with gcc instead of g++

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.

`go build` versus `go build file.go`

I am having trouble building a very simple go program that calls c code via cgo.
My setup:
$: echo $GOPATH
/go
$: pwd
/go/src/main
$: ls
ctest.c ctest.h test.go
test.go contains:
package main
// #include "ctest.c"
// #include <stdlib.h>
import "C"
import "unsafe"
import "fmt"
func main() {
cs := C.ctest(C.CString("c function"))
defer C.free(unsafe.Pointer(cs))
index := "hello from go: " + C.GoString(cs)
fmt.Println(index)
}
ctest.h contains:
char* ctest (char*);
ctest.c contains:
#include "ctest.h"
char* ctest (char* input) {
return input;
};
When I run go build test.go I get a binary, test that I can run which prints the expected hello from go: c function
However when I run go build I get the error:
# main
/tmp/go-build599750908/main/_obj/ctest.o: In function `ctest':
./ctest.c:3: multiple definition of `ctest'
/tmp/go-build599750908/main/_obj/test.cgo2.o:/go/src/main/ctest.c:3: first defined here
collect2: error: ld returned 1 exit status
What is happening with go build that is not in go build test.go that is causing the error?
Read your code carefully. Read the error message. Correct your error:
// #include "ctest.h"
test.go:
package main
// #include "ctest.h"
// #include <stdlib.h>
import "C"
import "unsafe"
import "fmt"
func main() {
cs := C.ctest(C.CString("c function"))
defer C.free(unsafe.Pointer(cs))
index := "hello from go: " + C.GoString(cs)
fmt.Println(index)
}
ctest.h:
char* ctest (char*);
ctest.c:
#include "ctest.h"
char* ctest (char* input) {
return input;
};
Output:
$ rm ./test
$ ls
ctest.c ctest.h test.go
$ go build
$ ls
ctest.c ctest.h test test.go
$ ./test
hello from go: c function
$

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
)

GDB can't debug the go program within cgo code

example files
src/test.go
package main
import (
. "clib"
)
func main() {
a := "123";
b := "456";
c := "789";
println(a,b,c);
Output("ABC");
}
src/clib/clib.h
#ifndef CLIB
void output(char* str);
#endif
src/clib/clib.c
#include "clib.h"
#include <stdio.h>
void output(char* str)
{
printf("%s\n", str);
}
src/clib/clib.go
package clib
/*
#cgo CFLAGS:-g
#include "clib.h"
*/
import "C"
func Output(s string) {
p := C.CString(s);
C.output(p);
}
exec code
go build -gcflags "-N -l" test.go
gdb ./test
b 10
r
info locals // <- every variable's value is wrong!
Who can help me solve this problem, thank you very much.
My Environment:
ubuntu 11.04 i386
gdb 7.6
go 1.1
There is currently an open bug regarding this: https://code.google.com/p/go/issues/detail?id=5221
Debugging cgo with gdb worked in 1.0 but is currently broken in 1.1. It's being worked on.

Resources