[go question]cgo argument has go pointer to go pointer

Go调用C Code时,Go传递给C Code的Go Pointer所值的Go Memory中不能包含任何指向Go Memory的Pointer。

示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# filename: test.go
# compile: go build test.go
package main

/*
struct person {
int age;
char *name;
};

struct student {
int class;
struct person *p;
};

char* getname(struct student *s){
return s->p->name;
}

*/
import "C"

//import "fmt"

func main() {
var s C.struct_student
s.class = 12
var p C.struct_person
p.age = 10
p.name = C.CString("tony")
s.p = &p

C.getname(&s)
}
# Output:
# panic: runtime error: cgo argument has Go pointer to Go pointer

代码中出现了panic,并提示”cgo argument has Go pointer to Go pointer”。我们的代码违背了Cgo Pointer传递规则。即便让s.p指向struct自身内存也是不行的,比如s.p = &s.class

按照rules中的说明,如果传递的是一个指向struct field的指针,那么Go Memory专指这个field所占用的内存,即便struct中有其它field指向其它Go Memory也可以。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func main() {
var s C.struct_student
s.class = 12
//var p C.struct_person // 将Go分配的内存改为C中分配
p := (*C.struct_person)(C.malloc(4))
defer func(){
C.free(unsafe.Pointer(p))
}()
p.age = 10
p.name = C.CString("tony")
s.p = p

fmt.Println(C.GoString(C.getname(&s)))
}

当把在go中分配的struct person内存改为使用C的malloc函数在C中分配后,则执行不再报错,说明go与C交互,是各自管理各自的内存。

坚持原创技术分享,如果觉得文章对你有帮助,给点鼓励更好!