unexpected type: ... with cgo in Go - 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...

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
}

How to return go (array/slice/ist) to a C function

I have C code in which I am calling golang functions. I am able to do it for primitives data types (int/float etc.) but I want to return some other data structure like array/list/slice.
I could not find any solution on internet.
Looking for help.
Want to return a array/slice/list of string data type.
It would be helpful if you provide additional information, i.e. example code you are currently working on.
As stated from the Cgo documentation page:
Go array types are not supported; use a C pointer
To do so
hello.go
package main
// #include <stdlib.h>
import "C"
import "unsafe"
// StringSlice is a wrapper arround GoStringSlice to make it usable in C.
//export StringSlice
func StringSlice() **C.char {
x := GoStringSlice()
ret := C.malloc(C.size_t(len(x)) * C.size_t(unsafe.Sizeof(uintptr(0))))
// convert to usable format so we are able to fill it with data
pRet := (*[1<<30 - 1]*C.char)(ret)
for i, item := range x {
pRet[i] = C.CString(item)
}
return (**C.char)(ret)
}
func GoStringSlice() []string {
return []string{
"Hello",
"World",
}
}
func main() {}
hello.c
#include <stdio.h>
#include "hello.h"
int main() {
printf("Hello from C!\n");
char **slice = StringSlice();
int numItems = sizeof(slice) / sizeof(char *);
printf("Number of items: %d\n", numItems+1);
printf("String #0: %s\n", *slice);
slice++;
printf("String #1: %s\n", *slice);
return 0;
}
You have to execute go build -buildmode=c-archive hello.go which will generate a hello.h and hello.a.
The hello.a has to be compiled with your C code: gcc -pthread hello.c hello.a -o hello.

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))
}

How to use std::vector or other container in cgo of golang?

I want to malloc large number of objects in to memory.(about 100 million objects) because the gc of golang is not effective enough,so i need to use c/c++ to malloc memory and use std::vector to hold objects.
this is my code,i want use std container in cgo:
package main
import (
"fmt"
)
/*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
using namespace std;
void dosome(){
vector<int> ivec; // empty vector
for (vector<int>::size_type ix = 0; ix != 10; ++ix)
ivec[ix] = ix; // disaster: ivec has no elements
}
*/
// #cgo LDFLAGS: -lstdc++
import "C"
//import "fmt"
func main() {
C.dosome()
var input string
fmt.Scanln(&input)
}
and have error message below:
go run stddemo.go
# command-line-arguments
./stddemo.go:13:10: fatal error: 'vector' file not found
#include <vector>
^
1 error generated.
how can i set the include path or is there another idea?
While you can use C++ with CGo, you can't embed that code inside the .go file, since it ultimately gets built with a C compiler.
Instead, place your dosome function in a separate .cpp file in the same directory as the .go file, and declare your function to use C linkage. For example:
extern "C" {
void dosome() {
vector<int> ivec;
...
}
}
If you include a prototype for the function in the CGo comment in the .go file so you can call it from Go.
Since you have multiple files now, you can't use the go run foo.go shorthand any more (since it only compiles a single file). Instead, you will need to use go run package or go build package, where your code is located at $GOPATH/src/package.
Uhh I think your conclusions are a bit too fast. GC cost is driven by two things: The more garbage your program produces, the more the GC will have to run. Second: The more pointers there are to scan, the longer a single GC will take.
That is to say: as long as you put your 100 million things into a go slice and keep them there: the GC won't have to run much, because there's no garbage. And second: if your things don't contain pointers, GC time, should it still occur, will be fine.
So, my question is: do your things have pointers?
if you just want to call someone's golang code this is a quick ram inefficient way:
package main
import "C"
import "fmt"
import "unsafe"
func intArrayFromC (src unsafe.Pointer, sz int) []uint64 {
dest := make([]uint64, sz)
copy(dest, (*(*[1000000000]uint64)(unsafe.Pointer(src)))[:sz:sz])// big number dose not affect ram.
return dest
}
//export doPrint
func doPrint(src unsafe.Pointer, sz int){
var numbers []uint64 = intArrayFromC(src, sz);
for i := 0; i < len(numbers); i++ {
fmt.Printf("%d index: %d\n", numbers[i], i)
}
}
func main() {}
and the c++ code:
#include "print.h"
#include <string.h>
#include <vector>
int main() {
std::vector<GoUint64> numbers{99,44,11,00,2,33,44};
while (1) {
doPrint(numbers.data(), numbers.size());
}
return 0;
}

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
}

Resources