I am +1 for this. In my experience writing many foreign library bindings in Haskell (I've done it a lot,) the vast majority of people who will ever do this are going to do it in a library and offer it up there. As an author, I find it often pays off the most in the long (for users) to wrap things anyway - to expose abstractions the users will expect of the host language. This is often achievable, and I try to write as little supporting C code as possible when writing things like bindings. Rust (or Haskell) is so much more expressive than C, I'd rather import raw functions, unsafe or not (in Haskell this is IO vs. no IO type, a bit different from Rust, but I mostly mark them all as 'possibly firing missiles') and abstract over the low-level nastiness as much as possible in the 'host' language, and give good interfaces. This pays off in my experience in maintenance and ease of use for everyone.
I generally let raw FFI code sit in a separate sub module where people who Know What They Are Doing can touch stuff and live dangerously, and otherwise emphasize high level interfaces instead. They don't even need to be a lot more high level - just clear memory safety and say, unicode/thread awareness. You will often have to write lots of code in the host language for this support anyway, because some useful C libraries will have complications, or be oblivious to these concerns. They can otherwise be pretty direct mappings with some high level types, and you can abstract over the 'imperativeness' even more if you want, or add more static safety, etc. in other interfaces. I think this is a very good approach for users, although it comes with burden to the author it may seem. I realize that there is still room for a lot of design in the core libraries and the sort of Rust best practices (if there is such a thing yet,) but overall I've found no matter what you will have to do at least basic sanity checking and offer up some kind of respectable interface to your users. Nobody wants to write lots of raw pointer-y crash-y C-y style code in Rust, just like nobody using Haskell really wants to do the same thing. In practice I think there won't be much noise, any more than what is necessary in most cases anyway. And when I write Rust, I would expect the language to be informative of the fact I can violate memory safety, so I can take the necessary precautions and prepare myself for a long night. On Mon, Oct 15, 2012 at 10:27 AM, Marijn Haverbeke <[email protected]> wrote: >> The question I guess is how often this situation comes up. Is it just >> libmath? Or is this sort of thing extremely common when doing bindings? > > > Extremely common. I'm somewhat appalled that the blanket 'all C functions > are unsafe' idea is even being considered (and enthusiastically supported). > Yes, C code can segfault and do other nasty things if you call it > incorrectly. But wrapping every call to a C function in an unsafe block will > dilute the 'red flag' role of unsafe blocks to the point of making them just > painful noise, and wrapping the C functions themselves in a wrapper function > to make them safe is, in most cases, a wax nose -- the wrapper will not be > able to guarantee that the call won't go wrong, so no safety is added. > > Best, > Marijn > > > _______________________________________________ > Rust-dev mailing list > [email protected] > https://mail.mozilla.org/listinfo/rust-dev > -- Regards, Austin _______________________________________________ Rust-dev mailing list [email protected] https://mail.mozilla.org/listinfo/rust-dev
