转到 / Cgo - 如何访问 C 结构的字段?

我在Go中开发了一个应用程序,用于将音频文件从一种格式转码为另一种格式:


我使用使用 Cgo 绑定 FFmpeg C 库的 goav 库:https://github.com/giorgisio/goav/


戈夫图书馆; 具有一个类型定义,该定义将原始 FFmpeg 库 C-结构 AV输出格式转换为:package avformat


type ( 

   OutputFormat               C.struct_AVOutputFormat

)

在我的代码中,我有一个名为 的变量,该变量的类型是.outputFOutputFormatC.struct_AVOutputFormat


真正的结构有以下字段:CAVOutputFormat


name, long_name, mime_type, extensions, audio_codec, video_codec, subtitle_codec,..

以及许多领域。


请参见: https://ffmpeg.org/doxygen/2.6/structAVOutputFormat.html


我通过以下方式验证了情况并到达:fmt.Println(outputF)


{0x7ffff7f23383 0x7ffff7f23907 0x7ffff7f13c33 0x7ffff7f23383 86017 61 0 128 <nil> 0x7ffff7f8cfa0 <nil> 3344 0x7ffff7e3ec10 0x7ffff7e3f410 0x7ffff7e3ecc0 <nil> 0x7ffff7e3dfc0 <nil> <nil> <nil> <nil> <nil> <nil> 0 0x7ffff7e3e070 0x7ffff7e3e020 <nil>}

音频编解码器字段位于位置,包含586017


我使用包验证了字段名称:reflect


val := reflect.Indirect(reflect.ValueOf(outputF))

fmt.Println(val)

fmt.Println("Fieldname: ", val.Type().Field(4).Name)


Output:

Fieldname:  audio_codec

我尝试使用以下命令访问原始字段:audio_codecAVOutputFormat


fmt.Println(outputF.audio_codec)

ERROR: outputF.audio_codec undefined (cannot refer to unexported field or method audio_codec)



fmt.Println(outputF._audio_codec)

ERROR: outputF._audio_codec undefined (type *avformat.OutputFormat has no field or method _audio_codec)

正如我在Cgo文档中读到的:在Go文件中,可以通过在下划线前缀来访问作为Go中关键字的C结构字段名称:如果x指向带有名为“type”的字段的C结构,x._type访问该字段。无法在 Go 结构中表示的 C 结构字段(如位字段或未对齐的数据)在 Go 结构中被省略,替换为适当的填充以到达下一个字段或结构的末尾。


但我不知道我做错了什么。


编辑:好吧,肯定不需要下划线,因为audio_codec不是Go中的关键字。我现在明白了。但是仍然存在一个问题,为什么我无法访问CStruct字段“audio_codec”。


慕盖茨4494581
浏览 71回答 1
1回答

慕哥6287543

GO / CGO有一些特质,你在这里碰到:type OutputFormat C.struct_AVOutputFormat是 go&nbsp;类型声明,而不是别名。将其视为薄包装而不是别名可能会有所帮助。因此,C.struct_AVOutputFormat字段不会导出,这就是您获得OutputFormat != C.struct_AVOutputFormatERROR: outputF.audio_codec undefined (cannot refer to unexported field or method audio_codec)如果该字段被调用Audio_codec它将符合go对导出标识符的定义,我们可以访问它,但事实并非如此。有一种方法可以解决这个问题,但我建议在继续之前三思而后行,因为它使用不安全的指针,并且您的程序可能会在运行时失去可移植性和/或稳定性。如果您想了解更多信息,这是不安全指针的良好介绍。现在,如果您确实确定要执行此操作,解决方案是将指针转换为不安全的指针,然后将其转换为指向 的指针。请注意,这需要您加载 FFMPEG 标头才能获得OutputFormatC.struct_AVOutputFormatC.struct_AVOutputFormat//#cgo pkg-config: libavformat//#include <libavformat/avformat.h>import "C"import (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "unsafe"&nbsp; &nbsp; "github.com/giorgisio/goav/avformat")func getOutput() *avformat.OutputFormat {&nbsp; // calls out to avformat and gets an OutputFormat back}func main() {&nbsp; &nbsp; outputF := getOutput()&nbsp; &nbsp; coutput := *(*C.struct_AVOutputFormat)(unsafe.Pointer(outputF))&nbsp; &nbsp; fmt.Println(coutput.audio_codec) // This should now work}警告:我还没有测试cgo包配置和导入是否正确,但这适用于一个简单的C库,我站起来尝试一下。<libavformat/avformat.h>
打开App,查看更多内容
随时随地看视频慕课网APP