douyin7829 2018-04-19 22:19
浏览 507
已采纳

CGO:如何在Golang中使用指针从C中的数组访问数据

I'm writing an app for the windows platform using FFmpeg and it's golang wrapper goav, but I'm having trouble understanding how to use the C pointers to gain access to the data array they point to.

I'm trying to get the data stored in the AVFrame class and use Go to write it to a file, and eventually a texture in OpenGl to make a video player with cool transitions.

I think understanding how to cast and access the C data will make coding this a lot easier.

I've stripped out all the relevant parts of the C code, the wrapper and my code, shown below:

C code - libavutil/frame.h

#include <stdint.h>

typedef struct AVFrame {
#define AV_NUM_DATA_POINTERS 8
    uint8_t *data[AV_NUM_DATA_POINTERS];
}

Golang goav wrapper - I don't really know whats going on here with the unsafe.Pointers and casting but it gives me access to the underlying C code

package avutil

/*
    #cgo pkg-config: libavutil
    #include <libavutil/frame.h>
    #include <stdlib.h>
*/
import "C"
import (
    "unsafe"
)

type Frame C.struct_AVFrame

func AvFrameAlloc() *Frame {
    return (*Frame)(unsafe.Pointer(C.av_frame_alloc()))
}

func Data(f *Frame) *uint8 {
    return (*uint8)(unsafe.Pointer((*C.uint8_t)(unsafe.Pointer(&f.data))))
}

My Golang code

package main

import "github.com/giorgisio/goav/avutil"

func main() {
    videoFrame := avutil.AvFrameAlloc()

    data := avutil.Data(videoFrame)

    fmt.Println(data) // here i want the values from data[0] to data[7], but how?
}
  • 写回答

1条回答 默认 最新

  • dpepbjp126917 2018-04-21 23:59
    关注

    Since the library author did not construct a slice header for you to work with you will instead need to cast the return value you get to an unsafe.Pointer and then to a uintptr this will allow you to perform pointer arithmetic on it to get elements later in memory.

    Here's some example code that should run as-is on the go playground.

    package main
    
    import (
        "fmt"
        "unsafe"
    )
    
    func main() {
        nums := []uint8{1, 2, 3, 4, 5, 6, 7, 8}
    
        val := &nums[0] // val is the equivalent of the *uint8 the Data function returns
    
        ptr := unsafe.Pointer(val)
    
        sixthVal := (*uint8)(unsafe.Pointer(uintptr(ptr) + 5*unsafe.Sizeof(*val)))
    
        fmt.Println("Sixth element:", *sixthVal)
    }
    

    Of course, you will need to be very certain you know how many elements there are so that you do not access invalid memory.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?
  • ¥15 matlab(相关搜索:紧聚焦)