2015-03-06 28 views
5

Czasami dla API C może być potrzebny wskaźnik NULL.CGO, przekazywanie parametru NULL do funkcji C

jest to możliwe w CGO?

Na przykład, chcę przekazać null argument strcmp() w programie języka Go:

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

Jeżeli ustawić pca do nil występuje ten błąd:

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, ...) 

Tak, jak czy mogę przekazać NULL do strcmp?

Dzięki

+0

I nie korzystał z API C w Go, lecz aby umożliwić funkcja zaakceptować ' Null', możesz zrobić 'func StrCmp (a, b * string) int {...}' –

Odpowiedz

7

Jeśli chcesz przekazać NULL do funkcji C można po prostu przejść nil do niego.

Jednak nie jest to dokumentowane, co się stanie, gdy wyślesz NULL wskaźnik do funkcji strcmp(...). Zgaduję, że strcmp nie powiedzie się, gdy przechodzisz NULL do niego. Byłoby lepiej sprawdzić twoje wejście przed ręką i zwrócić błąd, gdy jedno z twoich wejść jest ustawione na zero.

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

razie potrzeby przykładem jak przekazać NULL do funkcji, która bierze NULL wskazówek:

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

7.1.4.1 standardu C określa, że ​​przekazywanie NULL do 'strcmp' powoduje niezdefiniowane zachowanie (ponieważ' strcmp' isn ' t udokumentowane przyjęcie wskaźników NULL). –

+0

Dzięki, @Sander, wypróbuję Twoje exmaples – tanbro