所以我在 swift 中有以下结构
typealias float = Float32
typealias Point = float2
typealias Int = UInt32
//This is a struct that is meant to be the elements in an array that is immensly acessable to c
//CAREFUL this is LIKELY mirrored in a different thing
public struct Info {
var position:Point = Point(x: 0, y: 0)
var strength:float = 1
var altitude:float = 3.141592 / 2.0
var azmuth:Point = Point(x: 0, y: 0)
var state:Int = 0
}
此结构存储在使用 Array(repeating: ...
每一帧我都会将一个指向该数组的指针传递到我的 C++ 代码中,这里我有一个镜像结构
struct Info {
float positionX;
float positionY;
float strength;
float altitude;
float azmuthX;
float azmuthY;
int state;
float pad; //WHy???
};
现在请注意它在那里的额外 float “pad”,因为在结构声明中没有它,当我去读取第一个元素以外的元素时,数据会偏移一个 float 的大小(事物将被移动一个字段)结束)。
为什么 C++ 结构上的 pad 字段是必需的? Swift 中额外的 float 或额外填充的原因是什么?
最佳答案
float2
是 C 类型 simd_float2
的 Swift 映射,即
定义于 <simd/vector_types.h
作为
/*! @abstract A vector of two 32-bit floating-point numbers.
* @description In C++ and Metal, this type is also available as
* simd::float2. The alignment of this type is greater than the alignment
* of float; if you need to operate on data buffers that may not be
* suitably aligned, you should access them using simd_packed_float2
* instead. */
typedef __attribute__((__ext_vector_type__(2))) float simd_float2;
重点是
The alignment of this type is greater than the alignment of float
您可以通过以下方式验证这一点
print(MemoryLayout<float>.alignment) // 4
print(MemoryLayout<float2>.alignment) // 8
这会导致 Swift 类型 Info
的对齐到 8,及其步幅(即偏移量
连续 Info
之间的字节数存储在数组中的元素)为 32。
print(MemoryLayout<Info>.alignment) // 8
print(MemoryLayout<Info>.stride) // 32
另一方面,C型struct Info
只有float
和int
成员,它们都具有 4 字节对齐。如果没有
最终float pad;
成员,数组中该类型的连续元素之间的偏移量是 28 字节,而不是 32。
这就解释了其中的区别。你真正应该做的是定义 仅 C 中的类型,并将该定义导入到 Swift 中。这是 保证保留内存布局的唯一方法, 正如苹果公司的乔·格罗夫(Joe Groff)在 Mapping C semantics to Swift :
If you depend on a specific layout, you should define the struct in C and import it into Swift for now.
关于Swift 结构外部填充,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49716569/