douqianxun8540 2019-05-24 11:48
浏览 279

如何在Go中将函数指针传递给C代码

I want to write a small go application for processing videos and decided to use this library goav which is a FFmpeg binding for go. However, it does not support reading the video straightaway from memory. As a workaround, I decided to call the C function directly.

The signature of the function I want to call is as follows.

AVIOContext *avio_alloc_context(
                  unsigned char *buffer,
                  int buffer_size,
                  int write_flag,
                  void *opaque,
                  int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
                  int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
                  int64_t (*seek)(void *opaque, int64_t offset, int whence));

The go code I wrote to call this -

package video

// #include<libavformat/avio.h>
import "C"
import (
  "bytes"
  "github.com/giorgisio/goav/avformat"
  "github.com/giorgisio/goav/avutil"
  "unsafe"
)

func DecodeStream(data *bytes.Buffer) {
  bufferSize := 8192
  formatContext := avformat.AvformatAllocContext()
  buffer := (*C.uchar)(avutil.AvMalloc(uintptr(bufferSize)))
  ioContext := C.avio_alloc_context(
    buffer,
    C.int(bufferSize),
    C.int(0),
    unsafe.Pointer(data),
    &[0]byte{},
    &[0]byte{},
    &[0]byte{}, 
  )                                       // <- error in this line
  formatContext.SetPb((*avformat.AvIOContext)(unsafe.Pointer(ioContext)))
  if formatContext.AvformatFindStreamInfo(nil) < 0 {
    panic("Couldn't find stream info")
  }
  println("DURATION: ", formatContext.Duration())
}

However, I am getting this error runtime error: cgo argument has Go pointer to Go pointer.

I tried replacing &[0]byte{} with nil too. Can't seem to get away!

  • 写回答

1条回答 默认 最新

  • doubao6936 2019-05-26 09:49
    关注

    The runtime error is actually complaining about the unsafe.Pointer(data) argument. The bytes.Buffer type has internal (Go) pointers, and cgo doesn't allow passing pointers to C if those pointers point to Go objects that contain Go pointers themselves.

    These rules are detailed in the cgo documentation here: https://golang.org/cmd/cgo/#hdr-Passing_pointers

    The short summary is that the Go garbage collector needs to be aware when Go pointers are modified. The Go compilers make sure that compiled code appropriately informs the garbage collector, but C compilers don't know to do this. So to prevent GC problems, cgo simply doesn't allow passing pointers like this.

    评论

报告相同问题?

悬赏问题

  • ¥15 聚类分析或者python进行数据分析
  • ¥15 逻辑谓词和消解原理的运用
  • ¥15 三菱伺服电机按启动按钮有使能但不动作
  • ¥15 js,页面2返回页面1时定位进入的设备
  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号