-
Notifications
You must be signed in to change notification settings - Fork 29
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
Added ArrayPointer pattern #68
Conversation
On mobile right now, but quick cpomment: the api looks unsound as you can pass in len that mismatches the ffi array. At very least that method would have to be unsafe. |
Alright, I just had another look, some more comments in random order
|
I won't argue that it's not unsafe, however, it's exactly equivalent to using the current FFISlice type, but just by passing the length as a parameter value rather than as a struct member: uint values[1];
pattern_array_pointer(&values, UINT_MAX); // Undefined behavior
my_library_sliceu32 slice;
slice.data = &values;
slice.len = UINT_MAX;
pattern_ffi_slice_1(slice); // Also undefined behavior
No problem with marking the |
I'd say there is a small difference :
There's a bit more written in the FAQ.
See above. I admit there is a bit of a 'philosophical' argument around soundness boundaries across FFI (e.g., one could make the argument that any incoming FFI call should always be treated as maximally unsound, but then you'd also have to consider In that model though each (Edit - with the basic idea of 'soundness' in Rust being whether you can use the safe language itself to create UB)
I still think if the main purpose of Edit Ah, another thought, maybe this can be done exclusively in the C# by just creating other overload with |
Ok I see the distinction, I mistakenly thought that the FFISlice fields were public in rust.
I considered something like a
|
- Made representation transparent - Marked `as_slice` function unsafe
Ah, just saw you pushed an update. I'd still prefer to first explore other avenues to get the C# backend to emit the right binding. My issue with going that route is that it seems to have little benefit over using raw pointer types from a Rust or any-other-language perspective. In Rust you'd still have to call In other languages (C, Python) that concept wouldn't translate to anything else than a fallback, and in C# it really only seems to affect On the other hand, I think a hint system to tweak FFI generation is needed and came up a few times in our own bindings. That said, I'm not strictly arguing that FFI hints are the problem to this particular issue; an even simpler alternatives could be just using
I don't quite understand, isn't
Yes, and I'd totally agree that in many cases this is the right approach. It's just that this particular pattern, IMO, "doesn't carry it's weight" with respect to the user-code saved, safety gains, or general applicability. (I might even change my opinion on this later on if more benefits became visible, just right now I don't see them). |
TBH I only added this method as a convenience so entirely happy to lose it if you feel it's unnecessary. It was not the purpose behind the pattern.
It's a new type but the idea of patterns is not a new concept for the library and was considerably simpler to implement than adding a new
My general philosophy is that it's preferable to give automated systems the correct information to allow them to make the right decisions rather than explicitly tell them what result you want. Of course, this is a very idealistic view and requires much pragmatism in it's application, but to explain in more depth my thought process regarding this feature: What I want on the surface is for the library to generate an If we simply 'override' what the library would usually do by telling it explicitly what result we want in C# specifically, via something like I'm not necessarily suggesting that the pattern approach I've employed here is the best way of conveying this information, it might be better done by some variety of attribute, however rather than simply correcting the C# output, I feel that it is far more useful to indicate the purpose of the pointer parameter as that ambiguity is the root of the problem. |
Thanks for the detailed reply. More on a side note, from a design paradigms perspective I think I mostly agree with your reasoning; (so far) I've probably just differed in what the underlying vs. surface problem is. Within this library I mostly look at things with a C-lens, and there a distinction between single-element and multi-element pointers doesn't really exist, so adding these types feel like fixing what could also be labeled "bad C# ergonomics" (w.r.t, declaring C# FFI interfaces and working with However since C#-like marshalling details (e.g., the question of Names tbd:
The generic Edit: bonus-bonus points if |
Have some time now to look at #71 so closing this PR. |
Added an ArrayPointer pattern. This is a lighter-weight alternative to the FFISlice pattern which allows expression of a pointer to an array of a type. This allows backends to generate more relevant bindings. Crucially, it forces the C# backend to declare the parameter as an
IntPtr
rather than aref T
(which makes little sense for an array of values).