dryb38654 2017-04-03 19:27
浏览 103
已采纳

重新包装C类型会导致Go中的类型转换错误

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:

  1. Understand why it fails, and
  2. Identify how I can change the packaging so that the function uses the Codec type that is defined in the avcodec package.

Thanks in advance.

  • 写回答

1条回答 默认 最新

  • dqg2269 2017-04-03 20:42
    关注

    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{}
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥15 想问一下树莓派接上显示屏后出现如图所示画面,是什么问题导致的
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)
  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化