Uh oh!
There was an error while loading. Please reload this page.
RFC: Relocate and improve c_str - #435
Conversation
Created the draft for improve-c_str.
canndrew
commented
Nov 4, 2014
One thing to note: This wouldn't remove |
thestinger
commented
Nov 4, 2014
I don't think this should be in the |
canndrew
commented
Nov 4, 2014
Also, as discussed in those issues, it might be best to split |
canndrew
commented
Nov 4, 2014
A few more thoughts...
Always defining
I think in general we're going to want a way of using other allocators with Rust types including standard types like |
mzabaluev
commented
Nov 4, 2014
@canndrew: No problem with |
thestinger
commented
Nov 4, 2014
The fact that the |
mzabaluev
commented
Nov 4, 2014
I don't see much value in mutable wrappers. For collection-wise mutations one can convert to a In my understanding, the primary purpose of |
Quoting Daniel Micay: [libc] is a low-level binding to the C standard library, not a dumping ground for abstractions related to C. rust-lang#435 (comment)
canndrew
commented
Nov 5, 2014
I've worked with |
mzabaluev
commented
Nov 5, 2014
@canndrew You make a good point in that the constructors could follow the C ownership conventions regarding pointer constness. So the ownership-taking constructors would take a |
ben0x539
commented
Nov 5, 2014
@thestinger the current organization of libc with all those nested modules already seems hard to reproduce automatically. Do you consider that a bug? |
thestinger
commented
Nov 5, 2014
@ben0x539: Yes, I think any organization or design decisions in libc that aren't present in the original C headers is a bug. I don't think splitting it up by standard or whatever else makes sense. It should correspond directly to what the platforms provide. |
ben0x539
commented
Nov 5, 2014
@thestinger System headers seem to feature-gate declarations using macros etc, should we bother translating that into our bindings? |
mzabaluev
commented
Nov 5, 2014
@thestinger, @ben0x539: perhaps the idea was to be able to switch off parts of the standards that are missing on some platform. The real libc API variation is probably more fractured, anyway. The issues of binding to libc should be discussed separately, I think. |
thestinger
commented
Nov 5, 2014
The APIs are inherently non-portable because they use very platform-specific types. For example, The APIs are generally not fully specified to there are many differences between platforms in that sense too. For example,
You're proposing that we put stuff into the C bindings that aren't provided by the C standard library. I think it's appropriate to discuss my opinion on that here. I don't think it makes sense to move libc further away from being auto-generated / matching the C headers. |
mzabaluev
commented
Nov 5, 2014
@thestinger I have already removed the question on moving to |
The convention in C APIs is to use constness to designate absence of ownership transfer, so using a `*mut libc::char` in the ownership-taking constructors may help prevent accidental misuse. Destructor functions on the C side normally take pointers to non-const data as well. rust-lang/rfcs#435 (comment)
mzabaluev
commented
Nov 5, 2014
I have a nagging idea that representation of an unowned buffer could be laid onto |
mzabaluev
commented
Nov 7, 2014
A quick census of implFoo{fnget_inner_string<'a>(&'aself) -> CChars<'a>{unsafe{CChars::wrap(raw::foo_get_inner_string(self))}}} |
mzabaluev
commented
Nov 13, 2014
As an experiment, I have added a branch for |
mzabaluev
commented
Nov 25, 2014
Now I'm getting doubts on whether there's real need for three types to represent a C string. |
alexcrichton
commented
Nov 25, 2014
@mzabaluev sorry I should have posted here sooner, but I wanted to give you an update on my progress as well. I've taken over this RFC from @aturon and have been giving this some thought recently. After thinking about this for awhile, I think that all our usage of C strings can be lumped into one of three categories:
I, like you, have been questioning the fundamental utility of The key idea here is that For use case (2), the two conversion functions to be located in the For use case (3) I'm still noodling out some ideas, but I'm thinking of a smart-pointer-style vector which will basically be what I'm also thinking of deprecating all these functions (in modules other than
What do you think of this? In general I don't want to have a huge proliferation of types to work with here, and I'd rather leverage byte slices as much as possible (that's basically what a C string is). |
mzabaluev
commented
Nov 26, 2014
@alexcrichton I think case (1) is currently addressed primarily by fnfrob<T:ToCStr>(s:T){
s.with_c_str(|p| {unsafe{ foreign::frob(p);}}}Note that The pointer-to-slice conversion functions will probably address most needs, except the efficient passing back to C as described above. C strings are byte slices with a twist, which can be made use of statically.
In your design, To summarize my proposed solutions for the cases you have listed:
|
alexcrichton
commented
Nov 27, 2014
I was hoping to totally remove the Ah yes, I didn't go into too much detail for (3)! I ended up writing a proto-RFC today about this topic, and I'll probably open it up soon-ish. I'd be very curious to see this feedback folded into this RFC though, it's always nice to have a few options to choose from! |
mzabaluev
commented
Nov 27, 2014
@alexcrichton Thanks for the document, I'll be happy to provide feedback on your proposal. The problem I see with trading Getting owned strings under |
alexcrichton
commented
Nov 30, 2014
@mzabaluev indeed! This is a bit of a tradeoff one way or another. I wouldn't expect the case of handing an owned string into Rust and then back into C would be too common, but using I'm fairly confident that we can regain a small string optimization, but I would prefer to stress a clear API in this area rather than micro-optimize from the start. We could add helper functions later always, but I think that using an inline vector of ~64 bytes or so would be pretty close to today's small string optimization. I've now opened the RFC as well: #494 |
mzabaluev
commented
Dec 27, 2014
I have redesigned the library, bringing it closer to @alexcrichton 's #494 and bringing it up to date with Rust library conventions. |
aturon
commented
Jan 2, 2015
@mzabaluev The competing #494 has just been accepted. You can see some details in the comment I added, but the basic point is that #494 takes a more conservative approach and should be extendable to the design you've proposed here over time, if a clear need to do so emerges. We also plan to grow Thanks again for your work drawing attention to this issue and proposing a concrete design! |
mzabaluev
commented
Jan 3, 2015
Fair enough, I can see the concerns. Thanks to all participants for your work on improving Rust! |
mzabaluev
commented
Jan 11, 2015
After some more development, I have published the crate as c_string. let reaction = c_str!("Awesome!");unsafe{ libc::puts(reaction.as_ptr())}; |
Forwarding Element Modifiers with "Splattributes"
Relocation and interface changes for the Rust library module
c_str.For the time being, the redesigned module is available as a
standalone project.
c_strmodule out ofstdto free the standard library frompublic type dependencies on
libc.CStringis made generic over a destructor type, allowing arbitrarydeallocation functions.
CStringto Rust slice types are namedparse_as_bytesandparse_as_utf8to reflect the scanning cost andthe possibility of failure (in the UTF-8 case).
library.
Resultfor conversions that may fail, with descriptive error types.Cloneimplementation onCStringdue to lack of purpose..as_mut_ptr()due to its potential for convenient evil.CStrArgfor passing string data to foreign functionsaccepting null-terminated strings.
IntoCStrto enable optimized conversions toCStrArg.Rejected ideas
Left here as context to the comments below:
CStringinto a low-level typeCStrBufanda length-aware
CStringto make computation costs explicit.CStringhad dynamically assigned destructors as arbitrary boxed closures.Prior issues