convert a []float32 to C *float - go

I want to pass the pointer to the first element of a slice []float32 to a C variable, but somehow I can't figure out how.
C Code:
typedef struct
{ const float *data_in ;
float *data_out ;
} SRC_DATA ;
Go:
mySlice := make([]float32, 20)
foo := C.SRC_DATA{}
foo.data_in = *C.float(&mySlice[0]) // here the program breaks
As far as I have understood, it should be possible to pass directly a pointer to the first element in the slice from Go to C, without using unsafe.Pointer().
The C function will then iterate over the slice (length known).
Any hints are appreciated!

You need to use a slice of C.float type instead of float32:
package main
/*
#include <stdio.h>
void test(float *in) {
printf("C %f %f\n", in[0], in[1]);
}
*/
import "C"
func main() {
in := []C.float{1.23, 4.56}
C.test(&in[0]) // C 1.230000 4.560000
}
Go doesn't allow to store a Go pointer in a Go allocated structure passed to Cgo:
package main
/*
#include <stdio.h>
typedef struct {
float *in;
float *out;
} SRC_DATA;
void test(SRC_DATA *data) {
printf("C %f %f\n", data->in[0], data->in[1]);
data->out[0] = 8.8;
data->out[1] = 9.9;
}
*/
import "C"
import "fmt"
func main() {
in := []C.float{1.23, 4.56}
out := make([]C.float, 2)
data := &C.SRC_DATA{in: &in[0], out: &out[0]}
C.test(data) // panic: runtime error: cgo argument has Go pointer to Go pointer
fmt.Println("Go", out)
}
But you can create a helper function in C:
package main
/*
#include <stdio.h>
typedef struct {
float *in;
float *out;
} SRC_DATA;
void test(SRC_DATA *data) {
printf("C %f %f\n", data->in[0], data->in[1]);
data->out[0] = 8.8;
data->out[1] = 9.9;
}
void test_helper(float *in, float *out) {
SRC_DATA data;
data.in = in;
data.out = out;
test(&data);
}
*/
import "C"
import "fmt"
func main() {
in := []C.float{1.23, 4.56}
out := make([]C.float, 2)
C.test_helper(&in[0], &out[0]) // C 1.230000 4.560000
fmt.Println("Go", out) // Go [8.8 9.9]
}
Alternatively you can allocate and free SRC_DATA structure in C:
package main
/*
#include <stdio.h>
#include <stdlib.h>
typedef struct {
float *in;
float *out;
} SRC_DATA;
void test(SRC_DATA *data) {
printf("C %f %f\n", data->in[0], data->in[1]);
data->out[0] = 8.8;
data->out[1] = 9.9;
}
SRC_DATA *alloc_src_data() {
return (SRC_DATA*)malloc(sizeof(SRC_DATA));
}
void free_src_data(SRC_DATA *p) {
free(p);
}
*/
import "C"
import "fmt"
func main() {
in := []C.float{1.23, 4.56}
out := make([]C.float, 2)
data := C.alloc_src_data()
defer C.free_src_data(data)
data.in = &in[0]
data.out = &out[0]
C.test(data) // C 1.230000 4.560000
fmt.Println("Go", out) // Go [8.8 9.9]
}

Related

Create a C struct array in Go

I am trying to call a C lib from a Go program using CGo. I have the following C files that makes up the C lib. But, I get the following error" cgo parameter has Go pointer to Go pointer". I am struck with creating a C struct array in Go.
caller.h
enum c_callerIdType{
user,
certificate
}
typedef struct _c_callerid
{
c_callerIdType type,
char* value
}c_callerId;
typedef struct _c_requiredprops{
char* operationName,
CallerId* caller_id_set,
int caller_id_set_size
}c_requiredProps;
int log_caller_details(c_requiredProps);
caller.c
#include "caller.h"
int log_caller_details(c_requiredProps* rp){
printf("Operation name is %s", rp->operationName);
// printf the callerid details
return 1;
}
I created a Go wrapper around this C library as follows.
main.go
package main
// #include "caller.h"
// #include <stdlib.h>
import "C"
import "fmt"
type CallerId struct{
type string
value string
}
type RequiredProperties struct{
operationName string
callerIds []CallerId
}
// a helper function to call in to the C lib
func callCFunc() int{
var cRequiredProps C.c_requiredProps
var requiredProps RequiredProperties
var userCaller CallerId
var certCaller CallerId
// create user caller
userCaller.type = "user"
userCaller.value = "user1"
// create certificate caller
certCaller.type ="certificate"
certCaller.value = "service1.widgetcorp.com"
requiredProps.operationName = "UpdateWidget"
requiredProps.callerIds = []{userCaller,certCaller}
// convert from Go struct to C struct
var cOpName = C.CString(requiredProps.operationName)
defer C.free(unsafe.Pointer(cOpName))
cRequiredProps.operationName = cOpName
var cCallerIds = make([]C.c_callerId, 2)
for i,callerId := range requiredProps.callerIds{
var cTempCallerId C.c_callerId
cTempCallerId.type = C.c_callerIdType(callerId.type)
var cValue = C.CString(callerId.value)
cTempCallerId.value = cValue
defer C.free(unsafe.Pointer(cValue))
cCallerIds[i] = cTempCallerId
}
// this line throws error "CGo parameter has Go pointer to Go pointer" --> cRequiredProps.caller_id_set = (*C.c_requiredProps) (unsafe.Pointer(&cCallerIds[0]))
cRequiredProps.caller_id_set_size=2
return 1
}
func main() int{
fmt.PrintLn(callCFunc())
}
What am I doing wrong? How do I create an array of C structs inside Go and call a C function?

C NULL type in CGO

I have a C function that returns NULL when an exception occurs. How can I check whether the returned value is NULL or not in Go since it has no built-in types to represent C NULL. Below is my code
retVal := C.myfunc()
if retVal == nil {
// handle the error
}
I think you can use nil to test if the c function returns NULL. Try the following code:
package main
/*
#include <stdio.h>
#include <stdlib.h>
int* cfunc(int i) {
if (i == 0) {
return NULL;
}
int *p = (int*)malloc(sizeof(int));
*p = 100;
return p;
}
*/
import "C"
import "fmt"
import "unsafe"
func call_cfunc(i int32) {
ret := C.cfunc(C.int(i))
if ret == nil {
fmt.Println("nil")
} else {
fmt.Println(*ret)
C.free(unsafe.Pointer(ret))
}
}
func main() {
call_cfunc(0)
call_cfunc(1)
}

Why mustSendSIGSEGV() will continue print, but syscall.Kill(pid, syscall.SIGSEGV) only print once

Can any one tell me why syscall.Kill(pid, syscall.SIGSEGV) only print "handlerSIGSEGV Sent by 0" once ,but mustSendSIGSEGV will print "handlerSIGSEGV Sent by 0" Unlimited times。
I want golang SIGSEGV pass to C, only handle once, not many times. Can anyone help me?
package main
/*
#include <stdio.h>
#include <signal.h>
#include <string.h>
struct sigaction old_action;
void handlerSIGSEGV(int signum, siginfo_t *info, void *context) {
printf("handlerSIGSEGV Sent by %d\n", info->si_pid);
}
void testSIGSEGV() {
struct sigaction action;
sigaction(SIGSEGV, NULL, &action);
memset(&action, 0, sizeof action);
sigfillset(&action.sa_mask);
action.sa_sigaction = handlerSIGSEGV;
action.sa_flags = SA_NOCLDSTOP | SA_SIGINFO | SA_ONSTACK;
sigaction(SIGSEGV, &action, &old_action);
}
*/
import "C"
import (
"os"
"syscall"
"time"
"fmt"
)
type Test struct {
Num int
}
func mustSendSIGSEGV(){
var r *Test
r.Num = 0
}
func main() {
// C.test()
C.testSIGSEGV()
pid := os.Getpid()
syscall.Kill(pid, syscall.SIGSEGV)
// mustSendSIGSEGV()
for {
// syscall.Kill(pid, syscall.SIGUSR1)
fmt.Print("33")
time.Sleep(time.Second)
}
}
From "The Go Programming Language" I see this:
If the non-Go code installs a signal handler for any of the synchronous signals (SIGBUS, SIGFPE, SIGSEGV), then it should record the existing Go signal handler. If those signals occur while executing Go code, it should invoke the Go signal handler (whether the signal occurs while executing Go code can be determined by looking at the PC passed to the signal handler). Otherwise some Go run-time panics will not occur as expected.

how to use share memory with Golang? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
How does golang share or read other processes shared memory?
I've checked some information, but did not find relevant information. Can anyone give me an example?
In the world of go, don't communicate by sharing memory; share memory by communicating. If you really want to have a try, you can call the C API with cgo:
wrapper.c:
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/types.h>
int my_shm_open(char* filename, int open_flag){
int shm_id;
key_t key;
key = ftok(filename, 0x03);
if(key == -1){
return -1;
}
if(open_flag)
shm_id = shmget(key, 4096, IPC_CREAT|IPC_EXCL|0600);
else
shm_id = shmget(key, 0, 0);
if(shm_id == -1){
return -1;
}
return shm_id;
}
int my_shm_update(int shm_id, char* content){
char* addr;
addr = (char*)shmat(shm_id, NULL, 0);
if(addr == (char*)-1){
return -1;
}
if(strlen(content) > 4095)
return -1;
strcpy(addr, content);
shmdt(addr);
return 0;
}
int my_shm_close(int shm_id){
shmctl(shm_id, IPC_RMID, NULL);
return 0;
}
char* my_shm_read(char* filename){
int shm_id;
char* addr;
char* s;
shm_id = my_shm_open(filename, 0);
if(shm_id == -1)
return NULL;
addr = (char*)shmat(shm_id, NULL, 0);
if(addr == (char*)-1){
return NULL;
}
s = (char*)malloc(strlen(addr) + 1);
strcpy(s, addr);
shmdt(addr);
return s;
}
reader.go
package main
// #include <stdlib.h>
// #include "wrapper.c"
import "C"
import "unsafe"
import "fmt"
func read(filename string) string {
f := C.CString(filename)
defer C.free(unsafe.Pointer(f))
s := C.my_shm_read(f)
defer C.free(unsafe.Pointer(s))
return C.GoString(s)
}
func main() {
fmt.Println(read("/tmp"))
}
writter.go:
package main
// #include <stdlib.h>
// #include "wrapper.c"
import "C"
import "unsafe"
import (
"log"
"time"
)
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
func open(file string) (int, error) {
f := C.CString(file)
defer C.free(unsafe.Pointer(f))
r := int(C.my_shm_open(f, C.int(1)))
if r == -1 {
return 0, &errorString{"error"}
}
return r, nil
}
func update(shm_id int, content string) error {
c := C.CString(content)
defer C.free(unsafe.Pointer(c))
r := int(C.my_shm_update(C.int(shm_id), c))
if r == -1 {
return &errorString{"update error"}
}
return nil
}
func close(shm_id int) error {
C.my_shm_close(C.int(shm_id))
return nil
}
func main() {
id, err := open("/tmp")
if err != nil {
log.Fatal(err)
}
defer close(id)
err = update(id, "hello world")
if err != nil {
log.Fatal(err)
}
time.Sleep(1e9 * 100)
}
run the writer, then the reader by go run filename.
The code is from here
golang: It is a programming language, so it does not relate to the shared memory that the operating system level things. Not to say golang not use shared memory, but this is not it need to be defined. Posix use shared memory, you can use syscall package, which contains a lot of system calls, as long as the reference c system call interface on the line.

How do I put a vector inside of a struct in Go?

I'm trying to put a vector variable inside a struct in Google's Go programming language. This is what I have so far:
Want:
type Point struct { x, y int }
type myStruct struct {
myVectorInsideStruct vector;
}
func main(){
myMyStruct := myStruct{vector.New(0)};
myPoint := Point{2,3};
myMyStruct.myVectorInsideStruct.Push(myPoint);
}
Have:
type Point struct { x, y int }
func main(){
myVector := vector.New(0);
myPoint := Point{2,3};
myVector.Push(myPoint);
}
I can get the vector to work in my main function just fine, but I want to encapsulate it inside a struct for easier use.
I'm not sure whether this is what you want, so leave a comment if it doesn't work:
package main
import "container/vector";
type Point struct { x, y int };
type mystruct struct {
myVectorInsideStruct * vector.Vector;
}
func main() {
var myMyStruct mystruct;
myMyStruct.myVectorInsideStruct = new(vector.Vector);
myPoint := Point{2,3};
myMyStruct.myVectorInsideStruct.Push(myPoint);
}
Not sure this is what you want, but:
package main
import (
"fmt";
"container/vector";
)
type myStruct (
struct {
myVectorInsideStruct vector.IntVector;
}
)
func main() {
v := new(myStruct);
v.myVectorInsideStruct.Init(0);
for i := 1 ; i < 10 ; i++ {
v.myVectorInsideStruct.Push(i);
}
fmt.Printf("v.myVectorInsideStruct: %v\n", v.myVectorInsideStruct.Data());
}

Resources