• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

将c语言的结构体定义变成对应的golang语言的结构体定义,并将golang语言结构体变量的 ...

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

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 strict
for 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 you
a 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.FILE
const 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 land
10 : 20
1 : 2
3 : 4
a & b should have incremented with 1
from Go land
2 : 3
4 : 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
}

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
安装go的步骤发布时间:2022-07-10
下一篇:
Go学习笔记(一)发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap