将Swift结构体指针传递给C函数

3
假设我有一个名为Foo的Swift结构体。
struct Foo
{
     var a,b,c : Float
     var d : Double
     init()
     {
        a = 0
        b = 0
        c = 0
        d = 0
     }
}

Swift中的sizeof(Foo)打印出24个字节,其中Float类型字段占用4个字节,Double类型占用8个字节,在arm64上还需要4个字节的填充。

因此,我认为结构体对齐没有特殊的Swift魔法,我们可以自由地将指针传递给内部C函数,以便使用NEON和Metal等技术,只要内置变量是联合体,但目前无法直接包含在Swift中。

不知何故,当我尝试使用ConstUnsafePointer<()>获取const void*(Swift中的常量不安全指针)时,

let a = Foo()
let b = &a

我在第二个表达式中遇到了严重的编译器错误。

'Foo' is not convertible to '@lvalue inout $T1'

我错过了什么,这是故意设计的吗?

更新部分

马丁R,感谢您的回答!然而,整个情况对我来说并不是很清楚。我的目标是创建一个方便的数学函数包装器,所以我想要实现 @infix 方法,比如乘法,并将所有内部原生内容隐藏在 C 之后。例如,在矩阵的情况下,这意味着我们需要从 a = &b*&c 的表达式中取出 ampersand,因为我没有从您的答案和文档中得到有没有一种绕过这个问题,从而在 @infix 方法实现范围内获得内存中的原始指针。

像这样:

@infix public func *(l: Mat4, r: Mat4) -> Mat4
{
    var m = Mat4()
    _internalMat4Multiply(&l, &r, &m)
}

_internalMat4Multiply是一个无返回值(void)的C方法,用于进行所有计算。

1个回答

7

有两个问题:您不能获取使用let定义的常量的地址,只能将变量的地址传递给函数参数。

假设您的C函数为:

void myFunc(const void *data);

那么这样就可以实现:

var a = Foo()
myFunc(&a)

然而,我们不应该假设C和Swift有相同的对齐方式,你最好是在你的C API中更好地定义结构:

struct Foo {
    float a;
    float b;
    float c;
    double d;
};

void myFunc(const struct Foo *data);

并且从Swift代码中使用它:

var a = Foo(a: 0, b: 0, c: 0, d: 0)
myFunc(&a)

谢谢回答,如果您能看一下更新的部分并告诉我您的想法,我会很高兴。 - Elijah Igny
@ElijahIgny:尝试将您的函数声明为@infix public func *(var l: Mat4, var r: Mat4) -> Mat4 - Martin R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接