我在 Go 中开发了一个应用程序,用于将音频文件从一种格式转码为另一种格式:
我使用使用 Cgo 的 goav 库来绑定(bind) FFmpeg C-libs:
https://github.com/giorgisio/goav/
goav 图书馆; package avformat
有一个 typedef 可以转换原始的 FFmpeg lib C-Struct AVOutputFormat:
type (
OutputFormat C.struct_AVOutputFormat
)
在我的代码中,我有一个名为 outputF
的变量OutputFormat
类型的那是一个 C.struct_AVOutputFormat
.C
真实 AVOutputFormat
结构有字段: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>}
音频编解码器字段位于位置 5
并包含 86017
我使用包 reflect
验证了字段名称:val := reflect.Indirect(reflect.ValueOf(outputF))
fmt.Println(val)
fmt.Println("Fieldname: ", val.Type().Field(4).Name)
Output:
Fieldname: audio_codec
我尝试访问该字段
audio_codec
原文AVOutputFormat
使用: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)
As i read in the Cgo documentation: Within the Go file, C's struct field names that are keywords in Go can be accessed by prefixing them with an underscore: if x points at a C struct with a field named "type", x._type accesses the field. C struct fields that cannot be expressed in Go, such as bit fields or misaligned data, are omitted in the Go struct, replaced by appropriate padding to reach the next field or the end of the struct.
但我不知道我做错了什么。
编辑:
可以肯定不需要下划线,因为 audio_codec 不是 Go 中的关键字。这我现在明白了。但仍然存在为什么我无法访问 CStruct 字段“audio_codec”的问题。
最佳答案
您在这里遇到的 GO/CGO 有一些特质:type OutputFormat C.struct_AVOutputFormat
去吧type declaration ,而不是别名。将其视为一个瘦包装器而不是别名可能会有所帮助。因此OutputFormat != C.struct_AVOutputFormat
并且 C.struct_AVOutputFormat 的字段没有被导出,这就是你得到 ERROR: outputF.audio_codec undefined (cannot refer to unexported field or method audio_codec)
的原因
如果该字段被称为 Audio_codec,它将符合 go 对 exported identifier 的定义。我们可以访问它,但它不是。
有一种方法可以解决这个问题,但我建议在继续之前三思而后行,因为它使用不安全的指针,并且存在您的程序可能在运行时失去可移植性和/或稳定性的风险。 This is a good intro to unsafe pointers如果您想了解更多信息。
现在,如果您确实确定要这样做,解决方案是将指针转换为 OutputFormat
转换为不安全的指针,然后将其转换为指向 C.struct_AVOutputFormat
的指针.请注意,这需要您加载 FFMPEG header 以获取 C.struct_AVOutputFormat
的定义。
//#cgo pkg-config: libavformat
//#include <libavformat/avformat.h>
import "C"
import (
"fmt"
"unsafe"
"github.com/giorgisio/goav/avformat"
)
func getOutput() *avformat.OutputFormat {
// calls out to avformat and gets an OutputFormat back
}
func main() {
outputF := getOutput()
coutput := *(*C.struct_AVOutputFormat)(unsafe.Pointer(outputF))
fmt.Println(coutput.audio_codec) // This should now work
}
警告:我没有测试过 cgo 包配置和 <libavformat/avformat.h>
导入是正确的,但这适用于我站起来尝试的一个简单的 C 库。
关于Go/Cgo - 如何访问 Cstruct 的字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68791044/