简体   繁体   English

将swift结构指针传递给C函数

[英]Passing swift struct pointer to C function

Let's say, I have Swift struct named Foo 比方说,我有一个名为Foo的Swift结构

struct Foo
{
     var a,b,c : Float
     var d : Double
     init()
     {
        a = 0
        b = 0
        c = 0
        d = 0
     }
}

Swift sizeof(Foo) prints 24 bytes, 4 bytes for Float fields, 8 for Double and 4 bytes of padding on arm64. Swift sizeof(Foo)打印24个字节,4个字节用于Float字段,8个用于Double,4个字节用于arm64。

So I consider, that there is no special Swift magic with structures alignment done, and we can freely pass pointers to it to internal C functions in order to use stuff like NEON and Metal, as long as built-in variables are unions, which currently can't be directly included into Swift 所以我认为,没有特殊的Swift魔法与结构对齐完成,我们可以自由地将指针传递给内部C函数,以便使用像NEON和Metal这样的东西,只要内置变量是联合,目前不能直接包含在Swift中

Somehow, when I try to get const void* to it (ConstUnsafePointer<()> in Swift) with 不知何故,当我试图获得const void *(Swift中的ConstUnsafePointer <()>)时

let a = Foo()
let b = &a

I get nasty compiler error on second expression 我在第二个表达式上遇到令人讨厌的编译错误

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

Did I miss something and this is done by design? 我错过了什么,这是通过设计完成的吗?

UPDATED PART 更新部分

Martn R, thanks for answer! Martn R,谢谢你的回答! Still, entire situation is not very clear for me. 不过,对我来说,整个情况并不是很清楚。 My aim was to create convenient Math stuff wrapper, so I wanted to implement @infix methods like multiplication and hide all internal native stuff behind C. In case of Matrices, for example, that means, that we need to pull ampersand right from a = &b*&c expressions, because I didn't get from your answer and Docs if there is a way to bypass this and get raw point from memory in the scope of @infix method implementation. 我的目标是创建方便的Math stuff包装器,所以我想实现像乘法一样的@ infix方法并隐藏C后面的所有内部本机东西。例如,对于Matrices,这意味着我们需要从a =中拉出&符号&b *&c表达式,因为如果有办法绕过这个并且在@infix方法实现的范围内从内存中获取原始点,我没有得到你的答案和Docs。

Like this: 像这样:

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

_internalMat4Multiply is void(void*, void*, void*) C-method, doing all the computations _internalMat4Multiply是void(void *,void *,void *)C方法,执行所有计算

There are two problems: You cannot take the address of a constant (defined with let ), and you can pass the address of a variable only to function parameters. 有两个问题:您不能获取常量的地址(使用let定义),并且您只能将变量的地址传递给函数参数。 Assuming that your C function is 假设你的C函数是

void myFunc(const void *data);

then this would work: 然后这会工作:

var a = Foo()
myFunc(&a)

However, instead of making assumptions about identical alignment in C and Swift, you should perhaps better define the structure in your C API: 但是,您可以更好地在C API中定义结构,而不是在C和Swift中对相同的对齐进行假设:

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

void myFunc(const struct Foo *data);

and use that from the Swift code: 并使用Swift代码:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM