2015-03-06 3 views
5

Иногда для C API может потребоваться указатель NULL.CGO, как передать параметр NULL функции C

это возможно в CGO?

Например, я хочу, чтобы передать нулевой аргумент strcmp() в программе 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) 
} 

Если установить pca в nil, эта ошибка:

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

Итак, как могу ли я передать NULL в strcmp?

Благодаря

+0

Я не использовал C API в Go, но, чтобы ваша функция, чтобы принять ' Null', вы можете сделать 'func StrCmp (a, b * string) int {...}' –

ответ

7

Если вы хотите передать NULL в функцию C можно просто передать nil в него.

Однако не задокументировано, что происходит, когда вы отправляете указатель NULL на функцию strcmp(...). Я предполагаю, что strcmp терпит неудачу, когда вы передаете ему NULL. Было бы лучше проверить ваш вход перед рукой и вернуть ошибку, если один из ваших входов установлен на ноль.

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

При необходимости пример того, как передать NULL в функцию, которая делает принимать NULL указатели:

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 стандарта C указывает, что передача NULL в 'strcmp' приводит к неопределенному поведению (поскольку' strcmp' isn ' t документировано, чтобы принимать указатели NULL). –

+0

Спасибо, @Sander, я попробую ваши примеры – tanbro

Смежные вопросы