如何在CGO中向Go函数传递C结构体并转换为Go结构体?
CGO中C函数向Go函数传递结构体的解决方案
核心问题修正
你的代码存在两个关键问题:一是C的struct Person定义在函数内部,Go无法识别该类型;二是Go回调函数用interface{}作为参数,没法直接解析C结构体。下面是具体解决步骤:
1. 把C结构体移到全局区域
C里的结构体必须定义在全局作用域,这样CGO才能为Go生成对应的类型:
#include <stdlib.h> #include <stdio.h> #include <string.h> // 全局定义结构体,让Go能识别 struct Person{ int age; char name[100]; }; __attribute__((weak)) void testCFunc() { struct Person pers; pers.age = 21; strcpy(pers.name, "John Doe"); // 推荐传指针,避免大结构体拷贝 goCallbackHandler(&pers); }
2. 定义匹配的Go回调函数参数
Go回调函数要直接接收*C.struct_Person类型(如果传值就用C.struct_Person,指针更高效),然后把C结构体字段逐个转换为Go结构体:
//export goCallbackHandler func goCallbackHandler(cPers *C.struct_Person) { // 转换为Go结构体 goPers := Person{ age: int(cPers.age), // 把C的char数组转成Go字符串,自动处理'\0'结束符 name: C.GoString(&cPers.name[0]), } fmt.Println("转换后的Go结构体:") fmt.Printf("年龄:%d,姓名:%s\n", goPers.age, goPers.name) }
3. 完整可运行代码
package main import ( "fmt" ) /* #include <stdlib.h> #include <stdio.h> #include <string.h> struct Person{ int age; char name[100]; }; __attribute__((weak)) void testCFunc() { struct Person pers; pers.age = 21; strcpy(pers.name, "John Doe"); goCallbackHandler(&pers); } */ import "C" type Person struct { age int name string } //export goCallbackHandler func goCallbackHandler(cPers *C.struct_Person) { goPers := Person{ age: int(cPers.age), name: C.GoString(&cPers.name[0]), } fmt.Println("接收并转换后的Go结构体内容:") fmt.Printf("年龄:%d,姓名:%s\n", goPers.age, goPers.name) } func main() { // 调用C函数触发回调 C.testCFunc() }
复杂结构体扩展提示
如果后续使用嵌套结构体、带指针成员的复杂结构体,处理逻辑一致:
- 先在C全局区域定义完整的结构体(包括嵌套的子结构体);
- Go中用
C.struct_XXX或*C.struct_XXX接收; - 指针类型字段需要用
unsafe.Pointer辅助转换,比如C的char*可以直接用C.GoString,如果是自定义结构体指针,转成*C.struct_SubXXX后再处理字段。
内容的提问来源于stack exchange,提问作者user1628525
相关产品推荐
相关产品推荐

