將c語言的結構體定義變成對應的golang語言的結構體定義,並將golang語言結構體變數的指標傳遞給c語言,cast C struct to Go struct

來源:互聯網
上載者:User

https://groups.google.com/forum/#!topic/golang-nuts/JkvR4dQy9t4

https://golang.org/misc/cgo/gmp/gmp.go

https://stackoverflow.com/questions/19910647/pass-struct-and-array-of-structs-to-c-function-from-go

https://studygolang.com/articles/6367

 

1、可以為c struct定義結構體函數,如下定義的列印函數,(你可能還可以定義改變結構體內部子field的函數,但我未驗證過):

working with a lot of typedefs in cgo is a real pain (Go's typing rules are simply too strictfor a C programmer).I'd suggest you create a wrapper function in C (or Go) to create the structure for you.  for printing, you can define the String method on real type of structure (it won't be portable,as it depends the real type name of the C struct, but it's certainly doable, and will save youa lot of work if you're debugging a C-Type-rich application)For example, 
package main /*struct CType { int a; char b; float c;};*/import "C" import "fmt" func (c _Ctype_struct_CType) String() string { return "hello" } func main() { fmt.Printf("%v\n", C.struct_CType{})}

其中的 _Ctype_struct_CType 寒氣來有點奇怪,起始不用驚慌,可以用後面的方法自動得到這種奇怪的命名的。

當然,上面的只是示範為 c struct 定義內建函數。如果你僅僅是在golang中列印 c struct,只需要像普通變數一樣直接傳給Print就可以了,如: fmt.Printf("%v\n", C.objstruct) 或 fmt.Println(C.objstruct)。

 

2、你可以將整個golang的結構體指標轉換成c語言的結構體指標,前提是golang 的結構體和c 的結構體定義是一一對應的(後面有介紹怎麼穿件一一對應的結構體),但是c語言的結構體指標無法直接轉換成golang語言的結構體指標:

You can cast the entire struct via intermediate pointers. The conversion should work in either direction. There are probably other ways too, like encoding/binary. An example of the pointer approach follows:

 
package main import ( "fmt" "unsafe") // struct x {//  int y, z;// };//// int sum(struct x a) {//  return a.y + a.z;// }//import "C" type X struct{ Y, Z int32 } func main() {    a := &X{5, 7}    fmt.Println(a, "->", C.sum(*((*C.struct_x)(unsafe.Pointer(a)))))
}
3、上面第二步的做法並不安全,因為這種程式員自己定義的golang語言結構體可能和c語言的結構體並不一一對應,因此應該用下面的方法:This is not safe and Go doesn't guarantee compatible struct layout rules with gcc. for example, 8g currently aligns uint64 only to 4-byte boundary, but gcc aligns it to 8-byte boundary.If you want compatible structure layout, you can use "cgo -godefs". for example, given file.go:
package main /*#include <stdio.h>*/import "C" type File C.FILEconst Sizeof_File = C.sizeof_FILE 
 go tool cgo -godefs file.go                will generate a Go definition of type File that matches that of C's FILE.

cgo -godefs  是專門用來將c語言結構體轉換成golang語言對應的結構體的工具。

 

4、樣本:

package main/*#include <stdio.h>typedef struct {    int a;    int b;} Foo;void pass_struct(Foo *in) { printf("%d : %d\n", in->a, in->b); }void pass_array(Foo **in, int len) {    for(int i = 0; i < len; i++) {        pass_struct(in[i]);        in[i]->a += 1;        in[i]->b += 1;    }}*/import "C"import (    "fmt"    "unsafe")type Foo struct{ a, b int32 }func main() {    foo := Foo{10, 20}    foos := []*Foo{&Foo{1, 2}, &Foo{3, 4}}    fmt.Println("from C land")    C.pass_struct((*C.Foo)(unsafe.Pointer(&foo)))    C.pass_array((**C.Foo)(unsafe.Pointer(&foos[0])), C.int(len(foos)))    fmt.Println("a & b should have incremented with 1")    fmt.Println("from Go land")    for _, foo := range foos {        fmt.Printf("%d : %d\n", foo.a, foo.b)    }}
Output:
from C land10 : 201 : 23 : 4a & b should have incremented with 1from Go land2 : 34 : 5

5、樣本2:

將c語言的 char * 指標copy成 golang 的byte slice:

// convert c language char* to golang byte slice, and COPY source datas into dest slice    packet *C.char  // 該變數在c語言裡賦值    vlen := 512    b := make([]byte, vlen)    ii := C.int(0)    for i := 0; i < vlen; i++ {        ii = C.int(i)        // this is copy, not equal to the orignal pointer        b[i] = *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(packet)) + uintptr(unsafe.Pointer(C.int_to_charp(ii)))))    }

 

 

 

 

我自己的轉換的樣本:

c語言定義的結構體:

struct dnet_host {    struct dnet_key key;    char name[DNET_HOST_NAME_MAX];    char version[16];    time_t last_active;    time_t last_appear;    time_t last_time_changed;    uint32_t crc32;    uint32_t route_ip;    unsigned name_len;    uint16_t route_port;    uint8_t is_local;    uint8_t is_trusted;    enum dnet_host_route_types route_type;};

轉成golang對應的結構體 (type   DH   C.struct_dnet_host):

type DH struct {        Key                     _Ctype_struct_dnet_key        Name                    [256]int8        Version                 [16]int8        Last_active             int64        Last_appear             int64        Last_time_changed       int64        Crc32                   uint32        Route_ip                uint32        Name_len                uint32        Route_port              uint16        Is_local                uint8        Is_trusted              uint8        Route_type              uint32        Pad_cgo_0               [4]byte}

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.