Sometimes, a NULL pointer may be needed for a C API.
is that possible in CGO?
For example, I want to pass a null argument to strcmp()
in a Go language program:
package strutil
/*
#include <stdlib.h>
#include <string.h>
*/
import (
"C"
"unsafe"
)
func StrCmp(a, b string) int {
pca := C.CString(a)
defer C.free(pca)
pcb := C.CString(b)
defer C.free(pcb)
ret := C.strcmp(pca, pcb)
return int(ret)
}
If I set pca
to nil
, this error occurs:
Exception 0xc0000005 0x0 0x0 0x76828b21
PC=0x76828b21
signal arrived during cgo execution
strutil._Cfunc_strcmp(0x0, 0x761b00, 0x0)
strutil/_obj/_cgo_gotypes.go:79 +0x49
strutil.StrCmp(0x19, 0x10, 0x4bbf38, 0xa, 0x1fbc1f98, 0x0, 0x0, 0xffff, 0x0, 0x0, ...)
So, how can I pass NULL to strcmp?
Thanks
If you want to pass NULL to a C function you could simply pass nil
into it.
However it's not documented what happens when you send a NULL pointer to the function strcmp(...)
. I'd guess that the strcmp fails when you are passing NULL to it. It would be better to check your input on before hand and return an error when one of your inputs is set to nil.
package main
/*
#include <stdlib.h>
#include <string.h>
*/
import "C"
import (
"errors"
"fmt"
"unsafe"
)
func StrCmp(a, b *string) (int, error) {
if nil == a || nil == b {
return 0, errors.New("Both strings have to be set")
}
pca := C.CString(*a)
defer C.free(unsafe.Pointer(pca))
pcb := C.CString(*b)
defer C.free(unsafe.Pointer(pcb))
ret := C.strcmp(pca, pcb)
return int(ret), nil
}
func main() {
left := "Left"
right := "Right"
fmt.Println(StrCmp(&left, &right))
fmt.Println(StrCmp(&left, &left))
fmt.Println(StrCmp(nil, &right))
fmt.Println(StrCmp(&left, nil))
}
If necessary an example how to pass NULL to a function that does accept NULL pointers:
package main
/*
#include <stdio.h>
int am_i_null(int* pointer) {
if (NULL == pointer) {
return -1;
}
return *pointer;
}
*/
import "C"
import (
"fmt"
"unsafe"
)
func main() {
fmt.Println(C.am_i_null(nil))
var cInteger C.int = 8
fmt.Println(C.am_i_null(&cInteger))
var goInteger int = 7
fmt.Println(C.am_i_null((*C.int)(unsafe.Pointer(&goInteger))))
}