重新打包 C 类型导致 Go 中出现类型转换错误
Repackaging C types causes type cast error in Go
我正在尝试重新打包一些与现有 C 库集成的 go 代码。
以下完美运行。
文件 1:
package avcodec
type Codec C.struct_AVCodec
文件 2:
package avformat
//#cgo pkg-config: libavformat libavcodec
//#include <libavformat/avformat.h>
//#include <libavcodec/avcodec.h>
import "C"
import (
"unsafe"
)
type Codec C.struct_AVCodec
func (s *FormatContext) AvFormatGetVideoCodec() *Codec {
result := C.av_format_get_video_codec((*C.struct_AVFormatContext)(s))
return (*Codec)(result) // <- This works. Codec is defined in this package.
}
如果我尝试将编解码器从 File 2 引用或移动到单独的包中(例如 File 1),我会收到错误消息:
无法将 (func literal)((*C.struct_AVFormatContext)(s)) (type *C.struct_AVCodec) 转换为 *Codec
例如,这失败了:
package avformat
//#cgo pkg-config: libavformat libavcodec
//#include <libavformat/avformat.h>
//#include <libavcodec/avcodec.h>
import "C"
import (
"avcodec"
"unsafe"
)
func (s *FormatContext) AvFormatGetVideoCodec() *avcodec.Codec {
result := C.av_format_get_video_codec((*C.struct_AVFormatContext)(s))
return (*avcodec.Codec)(result) // <- This fails. Codec defined in avcodec.
}
这也失败了:
package avformat
//#cgo pkg-config: libavformat libavcodec
//#include <libavformat/avformat.h>
//#include <libavcodec/avcodec.h>
import "C"
import (
"avcodec"
"unsafe"
)
type Codec avcodec.Codec
func (s *FormatContext) AvFormatGetVideoCodec() *Codec {
result := C.av_format_get_video_codec((*C.struct_AVFormatContext)(s))
return (*Codec)(result) // <- This also fails. Codec is based on avcodec.Codec.
}
我愿意:
- 理解失败的原因,
- 确定如何更改包装,以便函数使用
avcodec
包中定义的 Codec
类型。
提前致谢。
由于 Go 表示类型的方式而失败。
例如,给定:
//Ex1
package avformat
//.. deleted for simplicity
type Codec C.struct_AVCodec
...和
//Ex2
package avcode
//.. deleted for simplicity
type Codec C.struct_AVCodec
在上面的代码中,ex1 中的 C.struct_AVCodec
与 ex2 中的 C.struct_AVCodec
不同,尽管它们在词法上相同。
具体来说,ex1中的完全限定类型是avformat._Ctype_struct_AVCodec
,而ex2是avcodec._Ctype_struct_AVCodec
这解释了为什么 package avformat
中试图将任何内容从外部类型(在本例中是从 package avcodec
)转换为本地 C.struct_AVCodec
的函数失败。
解决方案
为了让它工作,我依赖于类型断言。
package avformat
func (s *FormatContext) AvformatNewStream(c avcodec.ICodec) *Stream {
v, _ := c.(*C.struct_AVCodec)
return (*Stream)(C.avformat_new_stream((*C.struct_AVFormatContext)(s), (*C.struct_AVCodec)(v)))
}
...和
package avcodec
type ICodec interface{}
我正在尝试重新打包一些与现有 C 库集成的 go 代码。
以下完美运行。
文件 1:
package avcodec
type Codec C.struct_AVCodec
文件 2:
package avformat
//#cgo pkg-config: libavformat libavcodec
//#include <libavformat/avformat.h>
//#include <libavcodec/avcodec.h>
import "C"
import (
"unsafe"
)
type Codec C.struct_AVCodec
func (s *FormatContext) AvFormatGetVideoCodec() *Codec {
result := C.av_format_get_video_codec((*C.struct_AVFormatContext)(s))
return (*Codec)(result) // <- This works. Codec is defined in this package.
}
如果我尝试将编解码器从 File 2 引用或移动到单独的包中(例如 File 1),我会收到错误消息:
无法将 (func literal)((*C.struct_AVFormatContext)(s)) (type *C.struct_AVCodec) 转换为 *Codec
例如,这失败了:
package avformat
//#cgo pkg-config: libavformat libavcodec
//#include <libavformat/avformat.h>
//#include <libavcodec/avcodec.h>
import "C"
import (
"avcodec"
"unsafe"
)
func (s *FormatContext) AvFormatGetVideoCodec() *avcodec.Codec {
result := C.av_format_get_video_codec((*C.struct_AVFormatContext)(s))
return (*avcodec.Codec)(result) // <- This fails. Codec defined in avcodec.
}
这也失败了:
package avformat
//#cgo pkg-config: libavformat libavcodec
//#include <libavformat/avformat.h>
//#include <libavcodec/avcodec.h>
import "C"
import (
"avcodec"
"unsafe"
)
type Codec avcodec.Codec
func (s *FormatContext) AvFormatGetVideoCodec() *Codec {
result := C.av_format_get_video_codec((*C.struct_AVFormatContext)(s))
return (*Codec)(result) // <- This also fails. Codec is based on avcodec.Codec.
}
我愿意:
- 理解失败的原因,
- 确定如何更改包装,以便函数使用
avcodec
包中定义的Codec
类型。
提前致谢。
由于 Go 表示类型的方式而失败。
例如,给定:
//Ex1
package avformat
//.. deleted for simplicity
type Codec C.struct_AVCodec
...和
//Ex2
package avcode
//.. deleted for simplicity
type Codec C.struct_AVCodec
在上面的代码中,ex1 中的 C.struct_AVCodec
与 ex2 中的 C.struct_AVCodec
不同,尽管它们在词法上相同。
具体来说,ex1中的完全限定类型是avformat._Ctype_struct_AVCodec
,而ex2是avcodec._Ctype_struct_AVCodec
这解释了为什么 package avformat
中试图将任何内容从外部类型(在本例中是从 package avcodec
)转换为本地 C.struct_AVCodec
的函数失败。
解决方案
为了让它工作,我依赖于类型断言。
package avformat
func (s *FormatContext) AvformatNewStream(c avcodec.ICodec) *Stream {
v, _ := c.(*C.struct_AVCodec)
return (*Stream)(C.avformat_new_stream((*C.struct_AVFormatContext)(s), (*C.struct_AVCodec)(v)))
}
...和
package avcodec
type ICodec interface{}