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 package avcodec

    .

Thanks in advance.

+3


source to share


1 answer


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{}

      

+1


source







All Articles