Skip to content

Instantly share code, notes, and snippets.

@copyninja
Last active August 29, 2015 13:56
Show Gist options
  • Save copyninja/9045143 to your computer and use it in GitHub Desktop.
Save copyninja/9045143 to your computer and use it in GitHub Desktop.

Cgo with C pointer

I've been experimenting with cgo these days to avoid writing C code. I have some shared libraries from C which I want to use in the go programs. So I was trying the passing pointer to C function from Go and got a panic! So let the code do the talking below is the code I used.

#ifndef __POINTER_H__
#define __POINTER_H__
 
 
typedef struct {
int a;
int b;
float c;
} SampleStruct;
 
void GetSampleStruct(SampleStruct*);
 
#endif /* __POINTER_H_ */
#include <string.h>
#include "pointer.h"
 
void GetSampleStruct(SampleStruct *t){
    SampleStruct temp = {1,2,3.0};
 
    memcpy(t, &temp, sizeof(SampleStruct));
    return;
}
package main
 
/*
#include "pointer.h"
*/
import "C"
 
import "fmt"
 
type SStruct struct {
    s *C.SampleStruct
}
 
func main(){
    var ss SStruct
 
    fmt.Printf("Trying to read a structure by passing pointer\n")
    C.GetSampleStruct(ss.s);
    fmt.Printf("SampleStruct read!:\n")
    fmt.Printf("a: %d b: %d c: %f",ss.s.a, ss.s.b, ss.s.c)
}

So I'm just passing a pointer to C function GetSampleStruct which will use memcpy to copy values into this passed pointer location. When I compile and try to run this program I get a panic from go runtime. I'm pasting this below

Trying to read a structure by passing pointer
SIGSEGV: segmentation violation
PC=0x8048cdf
signal arrived during cgo execution

runtime.cgocall(0x8048ca0, 0xb7448f48)
        /usr/local/go/src/pkg/runtime/cgocall.c:149 +0x10c fp=0xb7448f3c
main._Cfunc_GetSampleStruct(0x0)
        _/home/vasudev/go/src/testpointer/_obj/_cgo_defun.c:50 +0x31 fp=0xb7448f48
main.main()
        /home/vasudev/go/src/testpointer/pointer.go:18 +0x46 fp=0xb7448f98
runtime.main()
        /usr/local/go/src/pkg/runtime/proc.c:220 +0xff fp=0xb7448fcc
runtime.goexit()
        /usr/local/go/src/pkg/runtime/proc.c:1394 fp=0xb7448fd0

goroutine 3 [syscall]:
runtime.goexit()
        /usr/local/go/src/pkg/runtime/proc.c:1394

eax     0x0
ebx     0x8169584
ecx     0xb75576d0
edx     0xb7448f0c
edi     0x18401140
esi     0x81703e0
ebp     0x8171a40
esp     0xbf9b83dc
eip     0x8048cdf
eflags  0x10282
cs      0x73
fs      0x0
gs      0x33

So it happens at line where I call C.GetSampleStruct function, so I guess this is because the ss.s is possibly unallocated but I'm not sure. I don't know if there is a malloc function available in Go to allocate pointers from C or if its safe to do so. I'm totally lost and looking forward for some Golang experts to give me some hints.

@davecheney
Copy link

You got a SEGV because you passed nil, here

main._Cfunc_GetSampleStruct(0x0)
_/home/vasudev/go/src/testpointer/_obj/_cgo_defun.c:50 +0x31 fp=0xb7448f48

because the zero value of SStruct.s is nil, it's a pointer

Try something like

var s C.SimpleStruct
C.GetSampleStruct(&s)

@copyninja
Copy link
Author

Yes that worked! for some reason I thought only allowed way to use C structures in go is *C.structname, not sure why I assumed that (possibly not reading the error message correctly). In any case your method works! Thanks a bunch :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment