digitalmars.D.learn - Calling C functions that modify a string
- Pat Maddox (35/35) Jun 14 2023 Hi there, I want to call a C function that upcases a string. I
- Steven Schveighoffer (25/72) Jun 15 2023 So interestingly enough, toStringz is pure, and returns an unrelated
- Steven Schveighoffer (4/7) Jun 15 2023 Oh wait, a pure function can return immutable data that isn't allocated
- Jonathan M Davis (4/8) Jun 15 2023 https://dlang.org/phobos/std_utf.html#toUTFz
- Steven Schveighoffer (3/12) Jun 15 2023 Oh nice, so `toUTFz!char` should work. Thanks!
- bachmeier (4/20) Jun 15 2023 Shouldn't it be `toUTFz!(char*)`? That's what I've been using to
- Steven Schveighoffer (3/20) Jun 15 2023 Yep. I didn't read so good...
Hi there, I want to call a C function that upcases a string. I have something working, I just want to check in here to see if there's a better approach that I'm missing. I ask because `std.string.toStringZ()` returns an `immutable char *`. As far as I can tell, I have two options: 1. Make the extern definition accept immutable. 2. Cast to `char *`. I opted for 2 because it seems that 1 would be confusing - the definition says immutable, but it mutates the string. Anyway, is this the D way to mutate a string from C, or is there another approach I'm unaware of? ``` extern (C) void upcase(char *); import std.stdio; import std.string; void main() { auto s = "hello d"; auto cs = cast (char *) std.string.toStringz(s); upcase(cs); writeln(std.string.fromStringz(cs)); } ``` It also works with: ``` extern (C) void upcase(immutable char *); import std.stdio; import std.string; void main() { auto s = "hello d"; auto cs = std.string.toStringz(s); upcase(cs); writeln(std.string.fromStringz(cs)); } ``` but it seems that "immutable" is a lie in that case.
Jun 14 2023
On 6/14/23 11:29 PM, Pat Maddox wrote:Hi there, I want to call a C function that upcases a string. I have something working, I just want to check in here to see if there's a better approach that I'm missing. I ask because `std.string.toStringZ()` returns an `immutable char *`. As far as I can tell, I have two options: 1. Make the extern definition accept immutable. 2. Cast to `char *`. I opted for 2 because it seems that 1 would be confusing - the definition says immutable, but it mutates the string. Anyway, is this the D way to mutate a string from C, or is there another approach I'm unaware of? ``` extern (C) void upcase(char *); import std.stdio; import std.string; void main() { auto s = "hello d"; auto cs = cast (char *) std.string.toStringz(s); upcase(cs); writeln(std.string.fromStringz(cs)); } ```So interestingly enough, toStringz is pure, and returns an unrelated type, so you shouldn't need to cast. However, for some reason, it does require a cast. That seems like a bug to me.It also works with: ``` extern (C) void upcase(immutable char *); import std.stdio; import std.string; void main() { auto s = "hello d"; auto cs = std.string.toStringz(s); upcase(cs); writeln(std.string.fromStringz(cs)); } ``` but it seems that "immutable" is a lie in that caseYeah, don't do it this way. just matching the type for a C prototype is very dangerous, especially if the C function doesn't obey the type constraints. Can I ask if this is a specific case of trying to use a C function to do "upper casing", or if this is a general question about C functions and modifying strings? Because we do have upper-casing facilities in both std.ascii and std.uni. But in general, if you want a mutable character array that's zero terminated, you need to make a copy with a zero terminator, but type it as mutable. I'm surprised there isn't a way to do this easily in the library. But if you need something that isn't wasteful, I would do something like this: ```d pure char *toMutStringz(const(char)[] str) { char[] result = str ~ "\0"; return result.ptr; } ``` -Steve
Jun 15 2023
On 6/15/23 9:18 AM, Steven Schveighoffer wrote:So interestingly enough, toStringz is pure, and returns an unrelated type, so you shouldn't need to cast. However, for some reason, it does require a cast. That seems like a bug to me.Oh wait, a pure function can return immutable data that isn't allocated on the heap. Nevermind. -Steve
Jun 15 2023
On Thursday, June 15, 2023 7:18:06 AM MDT Steven Schveighoffer via Digitalmars-d-learn wrote:But in general, if you want a mutable character array that's zero terminated, you need to make a copy with a zero terminator, but type it as mutable. I'm surprised there isn't a way to do this easily in the library.https://dlang.org/phobos/std_utf.html#toUTFz - Jonathan M Davis
Jun 15 2023
On 6/15/23 10:04 AM, Jonathan M Davis wrote:On Thursday, June 15, 2023 7:18:06 AM MDT Steven Schveighoffer via Digitalmars-d-learn wrote:Oh nice, so `toUTFz!char` should work. Thanks! -SteveBut in general, if you want a mutable character array that's zero terminated, you need to make a copy with a zero terminator, but type it as mutable. I'm surprised there isn't a way to do this easily in the library.https://dlang.org/phobos/std_utf.html#toUTFz
Jun 15 2023
On Thursday, 15 June 2023 at 15:53:57 UTC, Steven Schveighoffer wrote:On 6/15/23 10:04 AM, Jonathan M Davis wrote:Shouldn't it be `toUTFz!(char*)`? That's what I've been using to pass strings to C after someone here recommended it.On Thursday, June 15, 2023 7:18:06 AM MDT Steven Schveighoffer via Digitalmars-d-learn wrote:Oh nice, so `toUTFz!char` should work. Thanks! -SteveBut in general, if you want a mutable character array that's zero terminated, you need to make a copy with a zero terminator, but type it as mutable. I'm surprised there isn't a way to do this easily in the library.https://dlang.org/phobos/std_utf.html#toUTFz
Jun 15 2023
On 6/15/23 2:21 PM, bachmeier wrote:On Thursday, 15 June 2023 at 15:53:57 UTC, Steven Schveighoffer wrote:Yep. I didn't read so good... -SteveOn 6/15/23 10:04 AM, Jonathan M Davis wrote:Shouldn't it be `toUTFz!(char*)`? That's what I've been using to pass strings to C after someone here recommended it.On Thursday, June 15, 2023 7:18:06 AM MDT Steven Schveighoffer via Digitalmars-d-learn wrote:Oh nice, so `toUTFz!char` should work. Thanks!But in general, if you want a mutable character array that's zero terminated, you need to make a copy with a zero terminator, but type it as mutable. I'm surprised there isn't a way to do this easily in the library.https://dlang.org/phobos/std_utf.html#toUTFz
Jun 15 2023