总述
初学go,项目用到的库基本都是C/C++实现,需要大量写CGO。这两天遇到一些C定义的复杂结构体,所以准备梳理,个人总结如下。
- C里解析结构体,然后输出。可以参考下面链接的文章。
- go里定义兼容的结构体,然后使用。
- 类似第二条,但是不提前定义,使用C.struct_xxx的方法“硬写”
用C解析
请参考下文给出的用C做解析文章。
个人觉得既然都写go了,能用go实现的不想再去写C。不过,直觉认为某些情况下,使用C来解析时最稳妥的。可以在C里写个接口专门解析复杂结构体,直接输出json也不错。
go生成兼容结构体
一种方法是手写,容易出错还枯燥。另一种方法是使用CGO工具中的 -godefs
功能自动生成结构体声明。但是生成结果可能有偏差。
godefs
的参数要求是go文件。下面示例将C定义的结构体放在了序言中,也可以放在头文件中再引用。
文件名定为朴实无华的main.go
。
package main
/*
#define MAX_CLASSIFICATION_NUM 5
struct iRF_Classification
{
int candidate_num;
int index[MAX_CLASSIFICATION_NUM];
float confidence[MAX_CLASSIFICATION_NUM];
};
typedef struct iRF_Bound_Tag
{
float score;
struct iRF_Classification classification;
int x_left_top;
int y_left_top;
int x_right_top;
int y_right_top;
int x_left_bottom;
int y_left_bottom;
} iRF_Bound;
#define MAX_OBJECT_NUM 3
typedef struct iRF_Object_Tag
{
int num;
iRF_Bound bound[MAX_OBJECT_NUM];
} iRF_Object;
*/
import "C"
type IRF_Classification C.struct_iRF_Classification
type IRF_Bound C.iRF_Bound
type IRF_Object C.iRF_Object
const Sizeof_IRF_Classification = C.sizeof_struct_iRF_Classification
const Sizeof_IRF_Bound = C.sizeof_iRF_Bound
const Sizeof_IRF_Object = C.sizeof_iRF_Object
请注意示例中iRF_Classification
结构体,专门没有用typedef
与另外两个做区分。其在go中调用时,需要加上C.struct_
前缀。
此时执行go tool cgo -godefs main.go
,或者go tool cgo -godefs main.go > new_main.go
将输出结果只存存到文件中。得到的结果如下:
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs main.go
package main
type IRF_Classification struct {
Num int32
Index [5]int32
Confidence [5]float32
}
type IRF_Bound struct {
Score float32
Classification IRF_Classification
X_left_top int32
Y_left_top int32
X_right_top int32
Y_right_top int32
X_left_bottom int32
Y_left_bottom int32
}
type IRF_Object struct {
Num int32
Bound [3