2015-03-06 9 views
5

Manchmal kann ein NULL-Zeiger für eine C-API benötigt werden.CGO, wie übergeben NULL-Parameter an C-Funktion

ist das in CGO möglich?

Zum Beispiel habe ich ein Null-Argument strcmp() in einem Go-Sprachprogramm übergeben möchte:

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

Wenn ich pca-nil gesetzt, dieser Fehler auftritt:

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, wie kann ich NULL an strcmp übergeben?

Dank

+0

ich nicht den C-API in Go verwendet habe, aber Ihre Funktion zu ermöglichen, zu akzeptieren, ein ' Null ', könnten Sie tun' func StrCmp (a, b * string) int {...} ' –

Antwort

7

Wenn Sie eine C-Funktion NULL übergeben möchten Sie einfach nil hinein passieren könnte.

Es ist jedoch nicht dokumentiert, was passiert, wenn Sie einen Nullzeiger an die Funktion strcmp(...) senden. Ich würde vermuten, dass die strcmp fehlschlägt, wenn Sie NULL übergeben. Es wäre besser, Ihre Eingabe vorher zu überprüfen und einen Fehler zurückzugeben, wenn einer Ihrer Eingaben auf Null gesetzt ist.

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

Bei Bedarf kann ein Beispiel dafür, wie NULL an eine Funktion zu übergeben, die NULL-Zeiger akzeptiert:

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 des C-Standards spezifiziert, dass die Übergabe von NULL an' strcmp' zu undefiniertem Verhalten führt (da 'strcmp' isn ' t dokumentiert, um NULL-Zeiger zu akzeptieren). –

+0

Danke, @Sander, ich werde Ihre Exmaples versuchen – tanbro