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

Support for "recursive" unsafe_wrap #44

Closed
sloede opened this issue Oct 7, 2020 · 9 comments · Fixed by #46
Closed

Support for "recursive" unsafe_wrap #44

sloede opened this issue Oct 7, 2020 · 9 comments · Fixed by #46

Comments

@sloede
Copy link

sloede commented Oct 7, 2020

I was wondering if it is possible (currently, and if not, in general) to use unsafe_wrap in a recursive manner. What I am thinking about is the following:

@cstruct Inner {
  val::Int
}

@cstruct Outer {
  val::Int
  inner::Ptr{Inner}
}

outer_ptr = ... # get it from somewhere, possibly a C library
outer = unsafe_wrap(outer_ptr)

outer.val = 3 # this already works
outer.inner.val = 3 # as far as I understand, this does not yet work but would be great to have!

Is something like this at all feasible to do? It would be a great boost to convenience, but I immediately see the challenge that you probably would need to keep track of the types for which you can do this conversion automatically, i.e., for which there are @cstructs available.

@krrutkow
Copy link
Member

krrutkow commented Oct 7, 2020

Indeed, this would be a great feature! It will likely require use of another operator (basically like C does):

outer.inner->val = 3

So finding something like an -> operator that parses with the same-ish priority as the . does is the key to pulling this off.

@sloede
Copy link
Author

sloede commented Oct 7, 2020

So finding something like an -> operator that parses with the same-ish priority as the . does is the key to pulling this off.

Couldn't this be achieved by just skipping the first unsafe_wrap and defining an operator, e.g., -> for Ptr{<:Caccessor} (or something similar)? Then you could just do

outer_ptr->inner->val = 3

and would not have to worry about operator precedence.

@krrutkow
Copy link
Member

krrutkow commented Oct 7, 2020

Yes, that should be achievable... I've used C for over 25 years, and I just now learned this little tidbit of -> history: https://stackoverflow.com/a/13366168

@sloede
Copy link
Author

sloede commented Oct 8, 2020

Thanks for adding this feature so quickly. However, now I am wondering: How do I access the pointer values of a nested structure when I need that to, e.g., pass it back to a C function? Preferrably in a way that has zero overhead (i.e., without having to create a Caggregate type first and then querying it for the pointer value), since this is likely to occur in performance-critical sections as well.

@krrutkow
Copy link
Member

krrutkow commented Oct 8, 2020

I'm not exactly sure what you mean, but do you need to get a pointer to a nested struct? Something like this:

struct Outer {
   struct Inner {
      int i;
   } inner;
};

struct Outer o;
init(&o.inner);

@sloede
Copy link
Author

sloede commented Oct 8, 2020

No, I was rather thinking about

struct Inner {
  int i;
};
struct Outer {
  Inner* inner;
};
struct Outer o;
init(o.inner);

But the answer to your example would be interesting as well!

P.S.: Please excuse if this is not valid C code, I'm coming from C++ 🙈

@krrutkow
Copy link
Member

krrutkow commented Oct 8, 2020

Ahh, yes, that is precisely what #46 now allows. So this is what that would look like in Julia:

o = Outer(undef)
init(o.inner)  # init(ptr::Ptr{Inner}) = ...

Haha, strikingly similar...

@sloede
Copy link
Author

sloede commented Oct 8, 2020

OK, so o.inner will yield the original pointer to inner, while o.inner.i automatically "dereferences" the pointer to inner. Great feature!

@krrutkow
Copy link
Member

krrutkow commented Oct 8, 2020

Yes, any pointer to a Cstruct or Cunion will be automatically dereferenced when accessing fields, even:

x = o.inner  # x::Ptr{Inner}
x.i = 3
o.inner.i == 3

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