`go build` versus `go build file.go` - 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
$

Related

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.

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

Compiling CGO files in Golang package

I am trying to use CGO to bundle C files with a Golang package. Following instructions here:
https://karthikkaranth.me/blog/calling-c-code-from-go/
http://akrennmair.github.io/golang-cgo-slides/#1
https://golang.org/cmd/cgo/
I am getting this error:
# main
src/main/main.go:16:8: could not determine kind of name for C.free
src/main/main.go:23:10: could not determine kind of name for C.greet
here is the structure:
main.go just looks like:
package main
// #cgo CFLAGS: -g -Wall
// #include <stdlib.h>
// #include "genericc/greeter.h"
import "C"
import (
"fmt"
"unsafe"
)
func main() {
name := C.CString("Gopher")
defer C.free(unsafe.Pointer(name))
year := C.int(2018)
ptr := C.malloc(C.sizeof_char * 1024)
defer C.free(unsafe.Pointer(ptr))
size := C.greet(name, year, (*C.char)(ptr))
b := C.GoBytes(ptr, size)
fmt.Println(string(b))
}
and I run test.sh to build it:
#!/usr/bin/env bash
dir="$(cd `dirname "$0"` && pwd)"
export GOPATH="$dir"
cd "$dir"
export CGOFILES=main
go install main
but when I run the bash script I get that error.
I follow the instructions:
Command cgo
If the import of "C" is immediately preceded by a comment, that
comment, called the preamble, is used as a header when compiling the C
parts of the package. For example:
// #include <stdio.h>
// #include <errno.h>
import "C"
or
/*
#include <stdio.h>
#include <errno.h>
*/
import "C"
For example,
gocbuf.go:
package main
import (
"fmt"
"unsafe"
)
/*
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int printData(unsigned char *data) {
return printf("cData: %lu \"%s\"\n", (long unsigned int)strlen(data), data);
}
*/
import "C"
func main() {
// Allocate C data buffer.
width, height := 8, 2
lenData := width * height
// add string terminating null byte
cData := (*C.uchar)(C.calloc(C.size_t(lenData+1), C.sizeof_uchar))
// When no longer in use, free C allocations.
defer C.free(unsafe.Pointer(cData))
// Go slice reference to C data buffer,
// minus string terminating null byte
gData := (*[1 << 30]byte)(unsafe.Pointer(cData))[:lenData:lenData]
// Write and read cData via gData.
for i := range gData {
gData[i] = '.'
}
copy(gData[0:], "Data")
gData[len(gData)-1] = 'X'
fmt.Printf("gData: %d %q\n", len(gData), gData)
C.printData(cData)
}
Output:
$ go run gocbuf.go
gData: 16 "Data...........X"
cData: 16 "Data...........X"
$
Your code organization makes no sense to me.
You should have package greeter, which wraps C functions via cgo. For example,
src
└── greeter
├── greeter.c
├── greeter.go
└── greeter.h
with skeleton files
greeter.go:
package greeter
/*
#include "greeter.h"
*/
import "C"
greeter.c:
#include "greeter.h"
greeter.h
/* C header file */
To install the greeter package, simply use go install.
Don't use relative paths. Don't use bash scripts.
Thanks to #peterSO, this is what worked:
package main
// #cgo CFLAGS: -g -Wall
// #include <stdlib.h>
// #include "../genericc/greeter.h"
// #include "../genericc/greeter.c" // ! no whitespace after this line
import "C"
import (
"fmt"
"unsafe"
)
func main() {
name := C.CString("Gopher")
defer C.free(unsafe.Pointer(name))
year := C.int(2018)
ptr := C.malloc(C.sizeof_char * 1024)
defer C.free(unsafe.Pointer(ptr))
size := C.greet(name, year, (*C.char)(ptr))
b := C.GoBytes(ptr, size)
fmt.Println(string(b))
}

unexpected type: ... with cgo in Go

I'm new to Go and trying to learn how to call C from Go. I wrote this program to open a named semaphore, get the value and print it to the screen.
When I run it go build semvalue.go I get the error:
./semvalue.go:16:14: unexpected type: ...
What does this mean? What am I doing wrong?
package main
import "fmt"
// #cgo LDFLAGS: -pthread
// #include <stdlib.h>
// #include <fcntl.h>
// #include <sys/stat.h>
// #include <semaphore.h>
import "C"
func main() {
name := C.CString("/fram")
defer C.free(name)
fram_sem := C.sem_open(name, C.O_CREAT, C.mode_t(0644), C.uint(1))
var val int
ret := C.sem_getvalue(fram_sem, val)
fmt.Println(val)
C.sem_close(fram_sem)
}
Thank you.
The message is confusing, until you realize that the ... is the variadic portion of a C function. You can't use C variadic functions directly from Go, so you'll have to write a small wrapper in C to call sem_open.
A couple more notes:
C.free should be called with C.free(unsafe.Pointer(name))
val needs to be a *C.int
sem_getvalue uses errno, so you should call it with ret, err := C.sem_getvalue...

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