Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle nil #4

Closed
0rvar opened this issue Mar 19, 2022 · 5 comments
Closed

Handle nil #4

0rvar opened this issue Mar 19, 2022 · 5 comments

Comments

@0rvar
Copy link
Contributor

0rvar commented Mar 19, 2022

How do I handle nil returned from a swift function?
The *const pointer in SRObject is private, so I can't check result.0.is_null(). Any other option?

EDIT: Opened a PR: #5

@Brendonovich
Copy link
Owner

I never considered that Swift allowed nil values 😅
Adding a null check is one way to handle it, but I think it'd be better to allow using Rust's Option type.
I've done some testing and it seems that thanks to null-pointer optimisation, this can be done quite easily! Just gotta make SRObject contain a NonNull pointer and use #[repr(transparent)] rather than #[repr(C)]. Works with SRObject and SRArray.

@0rvar
Copy link
Contributor Author

0rvar commented Mar 23, 2022

@Brendonovich I am not quite sure what you mean.

In my case, the swift function is defined kind of like this:

@_cdecl("get_foo")
public func getFoo() -> Foo? {}

So, the returned object itself is nullable.
How would I then type the linked function in Rust?

I tried this:

#[link(name = "myfoolib")]
extern "C" {
    fn get_foo() -> SRObject<Option<FooObjc>>;
}

But this causes a segfault when I dereference the SRObject and nil was returned from swift

@0rvar
Copy link
Contributor Author

0rvar commented Mar 23, 2022

I managed to get this working, but only once I created this type manually:

#[repr(C)]
#[derive(Debug)]
enum NullablePtr<T> {
    Null,
    NonNull(T),
}

Then I could define the linked function like this:

#[link(name = "myfoolib")]
extern "C" {
    fn get_foo() -> NullablePtr<SRObject<FooObjc>>;
}

@Brendonovich
Copy link
Owner

@0rvar The solution I outlined was to do with the internals of SRObject, in your case all that would be required is giving get_foo the signature () -> Option<SRObject<FooObjc>>. The NonNull pointer will be held internally by SRObject, and will allow Rust to ensure that the Option works properly. I haven't pushed any changes yet but will soon so that you can try it out

@0rvar
Copy link
Contributor Author

0rvar commented Mar 23, 2022

Option<SRObject<T>> works perfectly with latest master! Thank you

@0rvar 0rvar closed this as completed Mar 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants