Elijah Igny
Elijah Igny

Reputation: 65

Passing swift struct pointer to C function

Let's say, I have Swift struct named Foo

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.

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

Somehow, when I try to get const void* to it (ConstUnsafePointer<()> in Swift) with

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! 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.

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

Upvotes: 3

Views: 4234

Answers (1)

Martin R
Martin R

Reputation: 539715

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. Assuming that your C function is

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:

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

void myFunc(const struct Foo *data);

and use that from the Swift code:

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

Upvotes: 7

Related Questions