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 case

Yeah, 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

Reply via email to