Repacking C types causes a cast error in Go
I am trying to repackage go code that integrates with the existing C library.
The following works great.
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 link or move Codec from file 2 to a separate package (like 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 would like to:
- Understand why this fails, and
- Determine how I can change the packaging so that the function uses the type
Codec
that is defined in the packageavcodec
.
Thanks in advance.
source to share
It failed because of the way Go represents types.
For example 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 above code C.struct_AVCodec
, ex1 is different from C.struct_AVCodec
ex2, although they are the same lexically the same.
In particular, the full type in ex1 is equal avformat._Ctype_struct_AVCodec
and ex2 isavcodec._Ctype_struct_AVCodec
This explains why functions in package avformat
that tried to do anything from external type (in this case from package avcodec
) to local C.struct_AVCodec
did not execute.
Decision
I relied on type assertions to get this to work.
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{}
source to share