我正在使用FFmpeg为Windows平台编写一个应用程序,它是golang包装器goav,但是我在理解如何使用C指针获取对数组的访问方面遇到了麻烦。
我试图获取存储在AVFormatContext类中的流以供使用,并最终将帧添加到OpenGl中的纹理以使视频播放器具有出色的过渡效果。
我认为了解如何转换和访问C数据将使编码变得容易得多。
我已经删除了C代码的所有相关部分,包装程序和我的代码,如下所示:
C代码-libavformat / avformat.h
typedef struct AVFormatContext {
unsigned int nb_streams;
AVStream **streams;
}
Golang Goav包装器
package avutil
//#cgo pkg-config: libavformat
//#include <libavformat/avformat.h>
import "C"
import (
"unsafe"
)
type Context C.struct_AVFormatContext;
func (ctxt *Context) StreamsGet(i uintptr) *Stream {
streams := (**Stream)(unsafe.Pointer(ctxt.streams));
// I think this is where it's going wrong, I'm brand new to this stuff
return (*Stream)(unsafe.Pointer(uintptr(unsafe.Pointer(streams)) + i*unsafe.Sizeof(*streams)));
}
我的Golang代码
package main
import "github.com/giorgisio/goav/avformat"
func main() {
ctx := &avformat.Context{} // the actual function to initiate this does an mallocz for the streams
stream := ctx.StreamsGet(0)
//do stuff with stream...
}
在C语言中,我似乎只需要执行stream[i],但这行不通,因此我在这里使用了我的问题中的技术为包装器添加了一个函数。但是我没有得到数据。看来我正在获取指向内存中随机位置的指针。那么,如何从golang中访问这些元素?任何资源也将有所帮助;我将为此花很多时间。
正如您所注意到的,问题出在以下代码中:
func (ctxt *Context) StreamsGet(i uintptr) *Stream {
streams := (**Stream)(unsafe.Pointer(ctxt.streams));
// I think this is where it's going wrong, I'm brand new to this stuff
return (*Stream)(unsafe.Pointer(uintptr(unsafe.Pointer(streams)) + i*unsafe.Sizeof(*streams)));
}
在代码中,变量streams
是双指针,因此将offset添加到的结果streams
也是双指针(即类型为**Stream
)。但是,在您的摘录中,它被强制转换*Stream
为不正确的。正确的代码是:
func (ctxt *Context) StreamsGet(i uintptr) *Stream {
streams := (**Stream)(unsafe.Pointer(ctxt.streams))
// Add offset i then cast it to **Stream
ptrPtr := (**Stream)(unsafe.Pointer(uintptr(unsafe.Pointer(streams)) + i*unsafe.Sizeof(*streams)))
return *ptrPtr
}
补充说明:
如果要避免在Go
side 进行指针运算,则可以定义一个_辅助_函数,用于访问C端的指针元素(即流),如下所示:
/*
void * ptr_at(void **ptr, int idx) {
return ptr[idx];
}
struct AVStream * stream_at(struct AVFormatContext *c, int idx) {
if (i >= 0 && i < c->nb_streams)
return c->streams[idx];
return NULL;
}
*/
import "C"
import (
"unsafe"
)
type Context C.struct_AVFormatContext
type Stream C.struct_AVStream
func (ctx *Context) StreamAt(i int) *Stream {
p := (*unsafe.Pointer)(unsafe.Pointer(ctx.streams))
ret := C.ptr_at(p, C.int(i))
return (*Stream)(ret)
}
func (ctx *Context) StreamAt2(i int) *Stream {
ret := C.stream_at((*C.struct_AVFormatContext)(ctx), C.int(i))
return (*Stream)(ret)
}
您可以选择ptr_at
接受通用(任何)双指针作为其参数的函数,也可以选择stream_at
仅接受指向其的指针作为其参数的更具体的函数AVFormatContext
。:前者的方法可以从任何双指针如用于接入元件AVProgram **
,AVChapter **
等等。后一种方法是优选的,如果我们需要实现额外的处理,如边界检查。
问题内容: 我正在使用FFmpeg为Windows平台编写一个应用程序,它是golang包装器goav,但是我在理解如何使用C指针获取对其所指向的数据数组的访问方面遇到了麻烦。 我正在尝试获取存储在AVFrame类中的数据,并使用Go将其写入文件,最后使用OpenGl中的纹理使视频播放器具有出色的过渡效果。 我认为了解如何转换和访问C数据将使编码变得容易得多。 我已经删除了C代码的所有相关部分,包
此类的目的是模拟二进制搜索树的功能。在下面的代码中,我试图将它从一个结构和一堆函数改编成一个包装类,称为BST。但是,我不确定的一件事是如何从节点结构中访问“根”。Root当前在BST类中声明。 具体来说,在show函数中。它不像把它和其他函数放在节点中那样简单,因为根需要是唯一的,并且新节点至少被调用一次。Show将不会在当前状态下编译,我不确定从这里开始。
在 C 语言中,数组名,&数组名,&数组首元素保存的都是同一个地址 #include <stdio.h> int main(){ int arr[3] = {1, 3, 5}; printf("%p\n", arr); // 0060FEA4 printf("%p\n", &arr); // 0060FEA4 printf("%p\n", &a
问题内容: 我目前正在学习使用Go语言编程。我在理解Go指针时遇到了一些困难(并且我的C / C ++现在很遥远…)。例如,在“第52号游览”中(http://tour.golang.org/#52),我读到: 但是如果不是 我写: 甚至: 反之亦然: 我得到了完全相同的结果。有区别吗(在内存方面,等等)? 问题答案: 您的示例使用两种Go语言规则: 可以从具有值接收器的方法派生具有指针接收器的方
问题内容: 指向数组的指针,比方说: 我无法访问该变量,上面的代码用于使其更加清晰。 另外,我知道数组的大小,但是不是恒定的,它会根据运行时而变化。 现在,我想使用已知的指针,大小以及数据类型初始化切片或数组。 我想出了以下代码: 但是这种方法是否可以进行内存复制(可能效率不高)? PS我还尝试了以下两种方法, 但它将在运行时失败,我现在知道其原因。 问题答案: 前言: 您应该知道:如果将指针作为
C++ 指针 在我们讲解指针数组的概念之前,先让我们来看一个实例,它用到了一个由 3 个整数组成的数组:#include <iostream> using namespace std; const int MAX = 3; int main () { int var[MAX] = {10, 100, 200}; for (int i = 0; i < MAX; i++) { cout << "Va