У меня есть адское время, пытаясь выяснить, как получить обычную, изменяемую строку C (a char *) из строки D (неизменяемой (char) []), чтобы Я могу передать персональные данные в старый код C. toStringz не работает, так как я получаю сообщение о том, что я не могу неявно преобразовать выражение (toStringz (this.fileName())) типа неизменяемого (char) * в char * ". Нужно ли мне воссоздать новый, изменяемый массив char и скопировать символы?
Получение простой char * из строки в D?
Ответ 1
Если вы можете изменить заголовок интерфейса D этого унаследованного кода C, и, вы уверены, что устаревший код C не будет изменять строку, вы можете заставить его принять const(char)*
, например,
char* strncpy(char* dest, const(char)* src, size_t count);
// ^^^^^^^^^^^^
Ответ 2
Да, это не очень, потому что результат непреложный.
Вот почему я всегда возвращаю изменяемую копию новых массивов в моем коде. Нет смысла делать их неизменными.
Решения:
Вы могли бы просто сделать
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;
}
Этот самый эффективный, но самый длинный.
( Изменить: Упс, у меня была опечатка в if
; исправлена ее.)
Ответ 3
Если вы хотите передать измененную функцию char*
в функцию C, вам потребуется выделить mutable char[]
. string
не будет работать, потому что он неизменен (char) []. Вы не можете изменять неизменяемые переменные, поэтому нет способа передать string
функции (C или иначе), которая должна изменить ее элементы.
Итак, если у вас есть string
, и вам нужно передать его функции, которая принимает char[]
, то вы можете использовать to!(char[])
или dup
и получить измененную копию. Кроме того, если вы хотите передать его функции C, вам нужно добавить '\0'
к ней, чтобы она была завершена с нулевым завершением. Самый простой способ сделать это - просто ~= '\0'
на char[]
, но более эффективным способом, вероятно, будет сделать что-то вроде этого:
auto cstring = new char[](str.length + 1);
cstring[0 .. str.length] = str[];
cstring[$ - 1] = '\0';
В любом случае вы передаете cstring.ptr
функции C, которую вы вызываете.
Если вы знаете, что функция C, которую вы вызываете, не будет изменять строку, то вы можете либо сделать, как предлагать KennyTM, и изменить C функции в D, чтобы взять const(char)*
, или вы можете записать строку. например.
auto cstring = toStringz(str);
cfunc(cast(char*)cstring.ptr);
Изменение сигнатуры функции C будет более корректным и менее подверженным ошибкам.
Похоже, мы можем изменить std.conv.to
, чтобы быть достаточно умным, чтобы превращать строки в строки с нулевым завершением при нажатии на char*
, const(char)*
и т.д. Итак, как только это будет сделано, получение измененного с нулевым изменением строка должна быть проще, но на данный момент вам просто нужно скопировать строку и добавить к ней '\0'
так, чтобы она была завершена нулем. Но независимо от того, вы никогда не сможете передать string
функции C, которая должна ее изменить, поскольку string
не может быть изменен.
Ответ 4
Без какого-либо контекста, какую функцию вы называете, трудно сказать, что является правильным решением.
Как правило, если функция C хочет изменить или записать в строку, она, вероятно, ожидает, что вы предоставите буфер и длину. Обычно я делаю это:
Выделить буфер:
auto buffer = new char[](256); // your own length instead of 256 here
И вызовите функцию C:
CWriteString(buffer.ptr, buffer.length);
Ответ 5
Вы можете попробовать следующее:
char a [] = "abc";
char * p = a;
Теперь вы можете передать указатель 'p' в массив в любой функции.
Надеюсь, что это сработает.