2016-08-05 32 views
2

我在學習go語言方面頗爲新穎,並且我開始成爲這種 語言的偉大愛好者。 我希望我很快會成爲一個好的地鼠。目前,我嘗試調用C函數 讀取影子文件,我的代碼是:從調用C函數開始

// #cgo CFLAGS: -D_POSIX_SOURCE=1 
// #include <stdlib.h> 
// #include <shadow.h> 
// size_t size_of_shadow() { return sizeof(struct spwd); } 
import "C" 
import "unsafe" 
import "fmt" 

type Shadow struct { 
    Name string 
    Passwd string 
} 

func Getspnam(name string) (*Shadow, error) { 
    cname := C.CString(name) 
    cspwd := (*C.struct_passwd)(C.malloc(C.size_of_shadow())) 
    buf := (*C.char)(C.malloc(1024)) 
    _, err := C.getspnam_r(cname, cspwd, 1024, &cpwd) 

    if unsafe.Pointer(cspwd) == unsafe.Pointer(uintptr(0)) { 
     C.free(unsafe.Pointer(cname)) 

     if err == nil { 
      err = fmt.Errorf("User %s not found", name) 
     } 

     return nil, err 
    } 

    s := Shadow{ 
     Name: C.GoString(cspwd.sp_namp), 
     Passwd: C.GoString(cspwd.sp_pwdp), 
    } 

    C.free(unsafe.Pointer(cname)) 
    C.free(unsafe.Pointer(cspwd)) 
    C.free(unsafe.Pointer(buf)) 

    return &s, nil 
} 

通過這個小項目和 當然函數的文檔的啓發:

https://github.com/LTD-Beget/passwd http://linux.die.net/man/3/getspnam

我在debian stretch上運行1.6版本,並與軟件包管理器一起安裝。 當我嘗試編譯我的文件,我得到了一個錯誤:

could not determine kind of name for C.getspnam_r 

但是當我打開頭文件shadow.h,功能卻出現在 文件。

+1

爲什麼你有'-D_POSIX_SOURCE = 1'? 'getspnam_r'函數不是POSIX,所以我認爲這個宏是干擾的。 – JimB

+0

因爲沒有此標誌,我得到了另一個錯誤,請參閱https://friendpaste.com/2EFrPk78Ghx96kE4CW0V2Z – Hobbestigrou

+1

使用'C.struct_spwd'而不是'C.struct_passwd'。編譯器應該能夠從那裏指出其餘的問題。你也應該把你的電話推遲到'免費',因爲當你提早回來時你沒有釋放內存。 – JimB

回答

0

我修正了我的錯誤。錯誤是使用的標誌有些是不必要的,並在結構的名稱上的錯字:

// #include <stdlib.h> 
// #include <shadow.h> 
// size_t size_of_shadow() { return sizeof(struct spwd); } 
import "C" 

import "C" 
import "unsafe" 
import "fmt" 

type Shadow struct { 
    Name string 
    Passwd string 
} 

func Getspnam(name string) (*Shadow, error) { 
    cname := C.CString(name) 
    defer C.free(unsafe.Pointer(cname)) 

    cspwd := (*C.struct_spwd)(C.malloc(C.size_of_shadow())) 
    defer C.free(unsafe.Pointer(cspwd)) 

    buf := (*C.char)(C.malloc(1024)) 
    defer C.free(unsafe.Pointer(buf)) 

    _, err := C.getspnam_r(cname, cspwd, buf, 1024, &cspwd) 

    if unsafe.Pointer(cspwd) == unsafe.Pointer(uintptr(0)) { 
     if err == nil { 
      err = fmt.Errorf("User %s not found", name) 
     } 

     return nil, err 
    } 

    s := Shadow{ 
     Name: C.GoString(cspwd.sp_namp), 
     Passwd: C.GoString(cspwd.sp_pwdp), 
    } 

    return &s, nil 
} 

新版本的代碼。