0

Trying to use a struct from ObjC to Swift doesn't seem to be that easy. I end up getting a Unsafe pointer that I don't know if I can cast reliably.

Here is the code:

//
// In OBJC land
//

// Type declared as a struct

typedef struct node {
    int children_count;
} node_t;

// Super class has a property

@property (nonatomic, assign, readonly) node_t *node;


//
// In SWIFT land
//

// Derived class tries to set the property inside the C struct


let n: UnsafeMutablePointer<node_t> = super.node // As swift compiler sees it
n.children_count = 0    // ERR!!! 

Do I really need to apply unsafeBitcast here or is there a simpler/safer and more elegant way to convert what seems to be a frequent scenario?

UPDATE:

I tried using memory to access the elements of the struct and I am getting a EXC_BAD_INSTRUCTION

var node: node_t = self.node.memory
node.children_count = 42

UPDATE CONT'D & FINALE

I got it to work. Thanks to @matt's patience for making sure I groked 'memory' access completely. The other trick is to realize the assignment in one continuous statement like this:

    var node: UnsafeMutablePointer<node_t> = self.node
    node.memory.children_count = 42

If I do the following, the change doesn't get committed passed the function call:

var node: node_t = self.node.memory
node.children_count = 42
3
  • "If I do the following, the change doesn't get committed passed the function call" Ah, very good point; yes, because in Swift the assignment of the struct to node causes that struct to be copied. Commented Jun 7, 2015 at 21:51
  • Done. Slow Sunday. Thanks @matt Commented Jun 7, 2015 at 21:53
  • Thanks for sticking with it - I really was prepared to send you a demo project if you needed it! :) Commented Jun 7, 2015 at 21:54

1 Answer 1

1

One problem is that this is not a "frequent scenario". In fact, this is a very odd thing to do:

@property (nonatomic, assign, readonly) node_t *node;

This thing (node_t) is a C struct. So why do you want a pointer to it? Perhaps you have no choice about this, but far and away the usual thing is simply to have the struct itself as a property:

@property (readonly) node_t *node;

In that way, the property arrives as a Swift struct called node_t, and if you have a var reference to it (not a let as you've written it), you can assign into its children_count directly, as you would expect.

If you insist on having a pointer, then you will have to dereference the pointer, won't you? You are not doing that. To do so, take the pointer's memory:

n.memory.children_count = 0
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for your answer. However, as you guessed, I don't have any choice but to use what's in there. The code is inherited from a objectiveC framework that I can't modify. I need a way to bridge the struct somehow. I hope there is a way.
See my revised answer. - Yes, I did guess that. :)
Also, are you sure you need super? If we are the subclass, we inherit this instance variable and self should work.
I merely used 'super' to examplify my use case (just to show that I am indeed inheriting it.) Terrible code that I wouldn't check in. Thanks for code reviewing with an eagle eye though.
So how about that little memory trick - is that working? (Of course it assumes that this property has been correctly initialized - i.e. the pointer is in fact pointing at something - but that is not a part of the question. If the pointer is not pointing at the desired struct, you would obviously crash.)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.