Obtaining a plain char* from a string in D?

老子叫甜甜 提交于 2020-01-03 08:00:35

问题


I'm having an absolute hell of a time trying to figure out how to get a plain, mutable C string (a char*) from a D string (a immutable(char)[]) to that I can pass the character data to legacy C code. toStringz doesn't work, as I get an error saying that I "cannot implicitly convert expression (toStringz(this.fileName())) of type immutable(char)* to char*". Do I need to recreate a new, mutable array of char and copy the characters over?


回答1:


If you can change the header of the D interface of that legacy C code, and you are sure that legacy C code will not modify the string, you could make it accept a const(char)*, e.g.

char* strncpy(char* dest, const(char)* src, size_t count);
//                        ^^^^^^^^^^^^



回答2:


Yeah, it's not pretty, because the result is immutable.

This is why I always return a mutable copy of new arrays in my code. There's no point in making them immutable.

Solutions:

You could just do

char[] buffer = (myString ~ '\0').dup; //Concatenate a null terminator, then dup

then use buffer.ptr as the pointer.

However:

This wastes a string. A better approach might be:

char[] buffer = myString.dup;
buffer ~= '\0'; //Hopefully this doesn't reallocate

and using buffer.ptr afterwards.


Another solution is to use a method like this one:

char* toStringz(in char[] s)
{
    string result;
    if (s.length > 0 && s[$ - 1] == '\0') //Is it null-terminated?
    { result = s.dup; }
    else { result = new char[s.length + 1]; result[0 .. s.length][] = s[]; }
    return result.ptr;
}

This one is the most efficient but also the longest.

(Edit: Whoops, I had a typo in the if; fixed it.)




回答3:


If you want to pass a mutable char* to a C function, you're going to need to allocate a mutable char[]. string isn't going to work, because it's immutable(char)[]. You can't alter immutable variables, so there is no way to pass a string to a function (C or otherwise) which needs to alter its elements.

So, if you have a string, and you need to pass it to a function which takes a char[], then you can use to!(char[]) or dup and get a mutable copy of it. In addition, if you want to pass it to a C function, you're going to need to append a '\0' to it so that it's zero-terminated. The easiest way to do that is just to do ~= '\0' on the char[], but the more efficient way would probably be to do something like this:

auto cstring = new char[](str.length + 1);
cstring[0 .. str.length] = str[];
cstring[$ - 1] = '\0';

In either case, you then pass cstring.ptr to the C function that you're calling.

If you know that the C function that you're calling isn't going to alter the string, then you can either do as KennyTM suggests and alter the C function's signature in D to take a const(char)*, or you can cast the string. e.g.

auto cstring = toStringz(str);
cfunc(cast(char*)cstring.ptr);

Altering the C function's signature would be more correct and less error-prone though.

It sounds like we may be altering std.conv.to to be smart enough to turn strings into zero-terminated strings when cast to char*, const(char)*, etc. So, once that's done, getting a zero-terminated mutable string should be easier, but for the moment, you pretty much just need to copy the string and append a '\0' to it so that it's zero-terminated. But regardless, you're never going to be able to pass a string to a C function which needs to modify it, because a string can't be mutated.




回答4:


Without any context on which function you're calling it's hard to say what is the right solution.

Typically, if the C function wants to modify or write to the string it probably expects you to provide a buffer and a length. Usually what I do is:

Allocate a buffer:

auto buffer = new char[](256);  // your own length instead of 256 here

And call the C function:

CWriteString(buffer.ptr, buffer.length);



回答5:


You can try the following :

char a[]="abc";

char *p=a;

Now you can pass pointer 'p' to the array in any function.

Hope it works.



来源:https://stackoverflow.com/questions/6393774/obtaining-a-plain-char-from-a-string-in-d

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!