Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opengl 在没有repr(C)的情况下安全地将struct传递给capi?_Opengl_Rust - Fatal编程技术网

Opengl 在没有repr(C)的情况下安全地将struct传递给capi?

Opengl 在没有repr(C)的情况下安全地将struct传递给capi?,opengl,rust,Opengl,Rust,根据Shepmaster在评论中的建议提出新问题 假设一个库定义了一个没有#[repr(C)]的结构。如果需要将结构传递给C API,有安全的方法吗?我是否应该担心Rust编译器会以C API不期望的方式更改结构的内存布局 我见过一些图书馆这样做。根据我的经验,当需要将结构传递给C函数时。transmute是否以某种方式消除了对#[repr(C)]的需求 如果我是定义结构的人,我就不会问了。我只想添加#[repr(C)]。问题是我想使用我不控制的库中的结构 老问题 我一直在使用,如果cgmath

根据Shepmaster在评论中的建议提出新问题

假设一个库定义了一个没有
#[repr(C)]
的结构。如果需要将结构传递给C API,有安全的方法吗?我是否应该担心Rust编译器会以C API不期望的方式更改结构的内存布局

我见过一些图书馆这样做。根据我的经验,当需要将结构传递给C函数时。
transmute
是否以某种方式消除了对
#[repr(C)]
的需求

如果我是定义结构的人,我就不会问了。我只想添加
#[repr(C)]
。问题是我想使用我不控制的库中的结构

老问题

我一直在使用,如果cgmath是,我可能会切换到


在这两个库的源代码中,我没有看到向量和矩阵结构的
#[repr(C)]
。那么这些库如何与OpenGLAPI兼容呢?当您将指针传递给向量和矩阵时,OpenGL需要特定的内存布局。我的理解是,如果没有
#[repr(C)]
,Rust结构的内存布局是未定义的

在中,我看到
mem::transmute
在将这些结构交给OpenGL之前被应用于这些结构。我可能误解了transmute,但该函数似乎保留了结构的内存布局。因此,如果布局一开始是错误的,那么在
transmute
之后仍然是错误的,对吗

我也考虑过。但是,通过设计,vecmath似乎缺少生成旋转矩阵等的辅助函数。诚然,我可以实现这些,但如果不必实现,那就太好了。无论如何,vecmath的设计是否通过使用数组而不是结构来避免内存布局问题

我见过一些图书馆这样做。根据我的经验,当需要将结构传递给C函数时,他们使用mem::transmute。transmute是否以某种方式消除了对#[repr(C)]的需求

没有

…但这很复杂

如果您有一个&Foo,并将其传递给C,而根本不进行编辑,那么将&Foo转换为*const C_void并传递给C调用是完全有效的,例如:

let fp = &foo as *const Foo as *const c_void
你可能会看到人们这样做是一个步骤,使用transmute

unsafe { ffi_call(transmute(&foo), ...) }
…但重要的是要理解transmute调用不会修改内存布局;但它确实消耗价值

因此,例如,该代码可能会在以后导致segfault:

{
  let foo = Foo { ... }
  unsafe { ffi_call(&foo as _ as *const c_void); }
}
这是因为指针&foo指向foo;但在范围结束后,foo停止存在;因此,如果以后使用它(例如ffi调用保留引用),将导致SEGFULT

您可能认为装箱(即移到堆中)解决了以下问题:

let foo = Box::new(Foo { ... })
unsafe { ffi_call(&*foo as *const c_void); }
……但事实并非如此;因为当盒子离开作用域时,它会被丢弃。然而,因为蜕变会移动价值观;这段代码将foo实例安全地移动到ffi调用中,以便以后使用;请注意,如果以后不恢复该值,则这是内存泄漏:

let foo = Box::new(Foo { ... })
unsafe { ffi_call(transmute(foo)); }
…但是使用transmute()将无法解决缺少repr(C)的问题,是的,您可以预期锈蚀会扰乱结构布局;这通常与drop FLAG有关,并且可以作为的一部分进行解析,因为drop FLAG是当前唯一与结构不同的内存布局;但由于RFC中没有明确涉及,我不会屏住呼吸

即tldr;如果需要在C中传递并修改结构,则需要repr(C);如果不行,那就不行了

Transmute用于其他原因,与此完全无关


**-->好吧,它可能会起作用,但你真正想要的是未定义的行为。如果您正在使用的库工作,可能是因为它碰巧工作。许多生锈的东西都是这样;在某些情况下可变的别名。。。但这确实意味着代码被破坏。

“这些库如何与OpenGL API兼容?”您的cgmath rs链接已经失效,但我在nalgebra的网站上没有看到任何声称与OpenGL兼容的内容。你能链接到一些表明它们应该是的东西吗?谢谢。我修复了链接。不,我没有看到任何明确的说法说它们与OpenGL兼容。然而,两者都明确地将自己称为“图形”。此外,nalgebra是一个基于OpenGL的引擎。因此,至少nalgebra非常强烈地暗示了兼容性。只需针对该存储库报告一个bug,IMO。无需询问我们:)事实上,我不相信这是一个bug。我这么问是因为我对生锈还不熟悉,我不相信我比这些库的作者更了解。因此,我在问我的分析是否正确。你可能希望把你的问题改为更一般的问题。您有使用OpenGL API的特定示例,但从概念上讲,您的问题更接近“转换非repr(c)结构并将其传递给c函数是否安全”。这可能会吸引一些不熟悉OpenGL的人,但他们一般都使用FFI.Perfect。那是我的直觉。我将看看是否可以在野外将repr(C)添加到这些库中。