c言語の構造体定義を対応するgolang言語の構造体定義に変更し、golang言語の構造体変数のポインタをc言語に渡します.cast C struct to Go struct...
11700 ワード
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,
その中の_Ctype_struct_CTypeは寒気が少しおかしくて、最初は慌てなくても、後の方法で自動的にこの奇妙な名前を得ることができます.
もちろん、上の説明はc structのために内蔵関数を定義することだけです.golangでc structを印刷するだけなら、普通の変数のようにPrintに直接伝えるだけでいいです.例えば、fmt.Printf("%v",C.objstruct)またはfmt.Println(C.objstruct).
2、golang全体の構造体ポインタをc言語の構造体ポインタに変換することができます.前提はgolangの構造体とcの構造体定義が1つ1つ対応していることです(後で、どのように着て1つ対応する構造体を紹介します)が、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:
3、上記の第2歩のやり方は安全ではありません.このようなプログラマーが自分で定義した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:
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、例:
5、例2:
c言語のchar*ポインタcopyをgolangのbyte sliceにする:
私自身の変換の例:
c言語定義の構造体:
golang対応構造体(type DH C.struct_dnet_host):
転載先:https://www.cnblogs.com/welhzh/p/9108603.html
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
", C.struct_CType{})
}
その中の_Ctype_struct_CTypeは寒気が少しおかしくて、最初は慌てなくても、後の方法で自動的にこの奇妙な名前を得ることができます.
もちろん、上の説明はc structのために内蔵関数を定義することだけです.golangでc structを印刷するだけなら、普通の変数のようにPrintに直接伝えるだけでいいです.例えば、fmt.Printf("%v",C.objstruct)またはfmt.Println(C.objstruct).
2、golang全体の構造体ポインタをc言語の構造体ポインタに変換することができます.前提はgolangの構造体とcの構造体定義が1つ1つ対応していることです(後で、どのように着て1つ対応する構造体を紹介します)が、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、上記の第2歩のやり方は安全ではありません.このようなプログラマーが自分で定義した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
*/
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
typedef struct {
int a;
int b;
} Foo;
void pass_struct(Foo *in) { printf("%d : %d
", 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
", 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
}
転載先:https://www.cnblogs.com/welhzh/p/9108603.html