英文:
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) // <- 这个是有效的。Codec在这个包中被定义。
}
如果我尝试将文件2中的Codec引用或移动到一个单独的包中(例如文件1),我会得到以下错误:
无法将(func literal)((C.struct_AVFormatContext)(s))(类型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) // <- 这个会失败。Codec在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) // <- 这个也会失败。Codec基于avcodec.Codec。
}
我想要:
- 理解为什么会失败,
- 找出如何更改打包方式,以便函数使用在
avcodec
包中定义的Codec
类型。
提前感谢。
英文:
I'm trying to repackage some go code that integrates with an existing C library.
The following works perfectly.
File 1:
package avcodec
type Codec C.struct_AVCodec
File 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.
}
If I try to reference or move Codec from File 2 into a separate package (eg. File 1) I get the error:
**cannot convert (func literal)((*C.struct_AVFormatContext)(s)) (type C.struct_AVCodec) to type Codec
For example, this fails:
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.
}
This also fails:
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.
}
I'd like to:
- Understand why it fails, and
- Identify how I can change the packaging so that the function uses the
Codec
type that is defined in theavcodec
package.
Thanks in advance.
答案1
得分: 1
这是由于Go语言对类型的表示方式导致的问题。
例如,给定以下代码:
//Ex1
package avformat
//.. 简化的代码已删除
type Codec C.struct_AVCodec
...和
//Ex2
package avcode
//.. 简化的代码已删除
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{}
英文:
This was failing due to how Go represents types.
For instance, given:
//Ex1
package avformat
//.. deleted for simplicity
type Codec C.struct_AVCodec
...and
//Ex2
package avcode
//.. deleted for simplicity
type Codec C.struct_AVCodec
In the code above, the C.struct_AVCodec
in ex1 is different from the C.struct_AVCodec
in ex2, even though the same are lexically the same.
Specifically, the fully qualified type in ex1 is avformat._Ctype_struct_AVCodec
, while ex2 is avcodec._Ctype_struct_AVCodec
This explains why the functions in the package avformat
that were trying to cast anything from an external type (in this case from package avcodec
) to the local C.struct_AVCodec
were failing.
Solution
To get this to work, I relied on type assertions.
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)))
}
...and
package avcodec
type ICodec interface{}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论