In the meantime Walter has added the patch to the latest DMD. Timon Gehr:
> That works without the cast. > That works without the ".ptr". Right. There is an implict conversion between the 2-word struct of the string to the nude pointer. > I was casting to char*, not const(char*). It is just that occasionally C > headers/bindings lack the const qualifier. Then passing a string literal > is achieved simplest by a cast to char*. In some situations like that I think that using someString.dup.ptr looks safer, or better using toStringz: http://d-programming-language.org/cutting-edge/phobos/std_string.html#toStringz I'd like toStringz to be pure and return a char*, so its result is assignable to immutable despite being fit for C functions without const too. To do this, it can't contain a ~ (string concat) because currently the ~ is not a pure function, it always returns a string, dstring, wstring. So I think this should compile: char[] foo(string s1, string s2) pure { return s1 ~ s2; } void main() {} And regarding toStringz(), this modified version seems to work as desired: import core.stdc.string; char* toStringz(immutable(char[]) s) pure nothrow in { // The assert below contradicts the unittests! //assert(memchr(s.ptr, 0, s.length) == null, //text(s.length, ": `", s, "'")); } out (result) { if (result) { auto slen = s.length; while (slen > 0 && s[slen-1] == 0) --slen; assert(strlen(result) == slen); assert(memcmp(result, s.ptr, slen) == 0); // overkill? } } body { /+ Unfortunately, this isn't reliable. We could make this work if string literals are put in read-only memory and we test if s[] is pointing into that. /* Peek past end of s[], if it's 0, no conversion necessary. * Note that the compiler will put a 0 past the end of static * strings, and the storage allocator will put a 0 past the end * of newly allocated char[]'s. */ char* p = &s[0] + s.length; if (*p == 0) return s; +/ // Need to make a copy auto copy = new char[s.length + 1]; copy[0..s.length] = s; copy[s.length] = 0; return copy.ptr; } void main() { string t = "hello"; char* s1 = toStringz(t); const(char*) s2 = toStringz(t); immutable(char*) s3 = toStringz(t); immutable(char)* s4 = toStringz(t); } > I don't think we really need that feature, I just think that removing it > breaks > existing code without a reason. > > extern(C) void puts(char* str); > void main() { > puts(cast(char*)"hello"); > } I prefer something like: extern(C) void puts(char* str); void main() { puts(Deconst!("hello".ptr)); } This avoids a cast, a Deconst template doesn't change the data, it never forces the string to be of a specific char type. Thank you for your answers, bearophile
