vala:如何将void *转换为uint []?

时间:2017-09-12 15:32:49

标签: vala

我想调用Gdk.Pixbuf.from_data()构造函数,以便将来自GStreamer的视频帧包装成pixbuf。构造函数接受指向内存的指针uint8[]。但是我有一个void *变量(Gst.Video.Frame.data[0]),它指向数据的开头。我知道uint8[]不仅仅是一个指针,而是一个了解内存开始位置和跨越距离的类型。但是对于Gdk.Pixbuf.from_data()来说,它并不重要,因为函数的C签名仅接受const guchar *,并且从其他参数(如步幅和高度)推断出长度。

那么......我如何正确地将void *指针包装到uint[]数组中?

Video.Frame frame = {};
...
var pixbuf = new Gdk.Pixbuf.from_data((uint8[])frame.data[0], ...);

上面的转换不起作用,因为vala会生成C代码,该代码将数据从memory复制到新创建的数组但长度不正确。首先,显而易见的是,vala本身无法知道void *点的长度,其次,我不需要任何复制,我只需要一个简单的转换。

1 个答案:

答案 0 :(得分:5)

我不知道你在哪里得到了void*,但是在大多数情况下,如果你在Vala中有一个指针,你做错了。有一些例外,主要是因为你使用libxml,但它们很少而且很少。您应该查看创建void*的代码并考虑是否有更好的方法,例如new uint8[x]而不是malloc(x)

void*转换为uint8[]只需要强制转换,但长度将设置为-1。 Gdk.Pixbuf.from_data实际上并不需要长度(它根据heightrowstride计算),所以这不应该是个问题。但是,一般来说,您可能希望执行类似

的操作
unowned uint8[] data = (uint8[]) memory;
data.length = whatever;

由于某些功能确实需要长度。许多人也不检查使用它的长度参数,这意味着无效长度很容易触发段错误。基本上,这是一个很好的习惯,它通常比检查每个参数更容易,看看是否设置了array_length = false CCode属性。

Vala生成副本的原因是Gdk.Pixbuf.from_data获取数据的所有权。您需要告诉Vala转移数据的所有权(使用(owned))。

全部放在一起:

unowned uint8[] data = (uint8[]) memory;
data.length = whatever;
Gdk.Pixbuf pb = new Gdk.Pixbuf.from_data(data, ...);

但请注意,当数据传递给Gdk.Pixbuf.from_data时,您仍会获得副本。除非您可以转让原始数据的所有权,否则由于Gdk.Pixbuf.from_data取得所有权,因此无法绕过副本。