Calling C functions that modify a string
Steven Schveighoffer
schveiguy at gmail.com
Thu Jun 15 13:18:06 UTC 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 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
More information about the Digitalmars-d-learn
mailing list