String 从D中的字符串获取普通字符*?
我花了很长时间试图弄清楚如何从一个D字符串(一个不可变的(char)[])中获得一个简单的、可变的C字符串(一个char*),以便将字符数据传递给遗留的C代码。ToString gz不起作用,因为我收到一个错误,它说我“无法将immutable(char)*类型的表达式(toString gz(this.fileName())隐式转换为char*”。我是否需要重新创建一个新的、可变的字符数组并复制这些字符?是的,这并不漂亮,因为结果是不可变的 这就是为什么我总是在代码中返回新数组的可变副本的原因。让它们不变是没有意义的 解决方案: 你可以这么做String 从D中的字符串获取普通字符*?,string,d,String,D,我花了很长时间试图弄清楚如何从一个D字符串(一个不可变的(char)[])中获得一个简单的、可变的C字符串(一个char*),以便将字符数据传递给遗留的C代码。ToString gz不起作用,因为我收到一个错误,它说我“无法将immutable(char)*类型的表达式(toString gz(this.fileName())隐式转换为char*”。我是否需要重新创建一个新的、可变的字符数组并复制这些字符?是的,这并不漂亮,因为结果是不可变的 这就是为什么我总是在代码中返回新数组的可变副本的原因
char[] buffer = (myString ~ '\0').dup; //Concatenate a null terminator, then dup
然后使用buffer.ptr
作为指针
然而:
这浪费了一根绳子。更好的方法可能是:
char[] buffer = myString.dup;
buffer ~= '\0'; //Hopefully this doesn't reallocate
然后使用buffer.ptr
另一个解决方案是使用如下方法:
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;
}
这是最有效的,也是最长的
(Edit:哎呀,我在
if
中有一个打字错误;已修复。)您可以尝试以下操作:
字符a[]=“abc”
char*p=a
现在可以在任何函数中将指针“p”传递给数组
希望它能工作。如果您可以更改该遗留C代码的D接口头,并且您确定遗留C代码不会修改字符串,您可以让它接受一个
常量(char)*
,例如
char*strncpy(char*dest,const(char)*src,size\u t count);
// ^^^^^^^^^^^^
如果没有调用函数的上下文,很难说什么是正确的解决方案
通常,如果C函数想要修改或写入字符串,它可能希望您提供缓冲区和长度。通常我做的是:
分配缓冲区:
auto buffer = new char[](256); // your own length instead of 256 here
并调用C函数:
CWriteString(buffer.ptr, buffer.length);
如果要将可变
char*
传递给C函数,则需要分配可变char[]
<代码>字符串不起作用,因为它是不可变的(char)[]。您无法更改不可变变量,因此无法将字符串
传递给需要更改其元素的函数(C或其他)
因此,如果您有一个字符串
,并且需要将其传递给一个接受char[]
的函数,那么您可以使用来!(char[])
或dup
并获取它的可变副本。此外,如果要将其传递给C函数,则需要在其上附加一个'\0'
,使其以零结尾。最简单的方法是在char[]
上执行~='\0'
,但更有效的方法可能是执行以下操作:
auto cstring = new char[](str.length + 1);
cstring[0 .. str.length] = str[];
cstring[$ - 1] = '\0';
在这两种情况下,您都将cstring.ptr传递给正在调用的C函数
如果您知道您正在调用的C函数不会改变字符串,那么您可以执行as并改变C函数在D中的签名,以获取一个const(char)*
,也可以强制转换字符串。e、 g
auto cstring = toStringz(str);
cfunc(cast(char*)cstring.ptr);
不过,更改C函数的签名会更正确,也更不容易出错
听起来我们可能正在将
std.conv.to
更改为char*
,const(char)*
,等等。因此,一旦完成,获得一个以零结尾的可变字符串应该会更容易,但目前,您几乎只需要复制字符串并在其上附加一个'\0'
,使其以零结尾。但是不管怎样,你永远无法将字符串
传递给需要修改它的C函数,因为字符串
是不能变异的。最好先做char[]buffer=(myString.dup~'\0')
复制字符串,然后追加\0
,这样就不会重复两次了(一次用于空concat,一次用于dup)@ratchetfreak:它仍然会realloc两次。如果编译器可以优化它,它不会。但是char[]buffer=(myString[]~'\0')
;`will only realloconce@ratchet:是的,但你不能依赖编译器来优化它。这会起作用,但如果接收代码实际上不需要任何变异,这不是一个好主意。我真的很困惑为什么你的答案有这么多的向上投票……OP没有提到他想要一个可变字符串吗?@Mehrdad,这已经得到了你的支持pvotes,因为OP可能不需要可变字符串。不过,最好包括如何获取可变字符串。