vala:如何将 void * 转换为 uint[]?
vala: how to cast void * to uint[]?
我想调用 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 *
指向的长度,其次,我不需要任何复制,我只需要一个简单的转换。
我不知道你从哪里得到 void*
,但在大多数情况下,如果你在 Vala 中有一个指针,那你就做错了。也有例外,主要是在您使用 libxml 时,但它们很少见。您应该查看创建 void*
的代码,并考虑是否有更好的方法,例如 new uint8[x]
而不是 malloc(x)
.
将 void*
转换为 uint8[]
只需要一次转换,但长度将设置为 -1。 Gdk.Pixbuf.from_data
实际上不需要长度(它是根据 height
和 rowstride
计算的),所以这应该不是问题。但是,一般来说,您可能想做类似
的事情
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
取得了所有权,因此无法绕过副本,除非您可以转让原始数据的所有权。
我想调用 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 *
指向的长度,其次,我不需要任何复制,我只需要一个简单的转换。
我不知道你从哪里得到 void*
,但在大多数情况下,如果你在 Vala 中有一个指针,那你就做错了。也有例外,主要是在您使用 libxml 时,但它们很少见。您应该查看创建 void*
的代码,并考虑是否有更好的方法,例如 new uint8[x]
而不是 malloc(x)
.
将 void*
转换为 uint8[]
只需要一次转换,但长度将设置为 -1。 Gdk.Pixbuf.from_data
实际上不需要长度(它是根据 height
和 rowstride
计算的),所以这应该不是问题。但是,一般来说,您可能想做类似
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
取得了所有权,因此无法绕过副本,除非您可以转让原始数据的所有权。