www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - string to char*

reply shd <alienballance gmail.com> writes:
Hello,
I'm having a problem in passing a value to char* expecting function
in D 2.0. Already tried:

to!(char*)("my string");

but it seems like there (Phobos) is no template like this. Then,
tried:

cast(char*)to!(char[])("my string")

which looked ok, but i think it's not a proper way to do that. Most
strings converted this way works properly, but once:

char* string1 = cast(char*)to!(char[])("my string 1");
char* string2 = cast(char*)to!(char[])("my string 2");

resulted:
string1 = "my string 1"
string2 = "my string 1my string 2"

I can't manage this problem, could You hint me?
Sep 11 2010
next sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
shd <alienballance gmail.com> wrote:

 Hello,
 I'm having a problem in passing a value to char* expecting function
 in D 2.0.

Why does the function expect a char*? If it is an external C function, and it might change the passed values, you should make a duplicate mutable string, or use char[] in lieu of string. If it is an external C function that will *not* change the passed values, and you have write access to the D headers to interface to C, use const char* instead. If no write access, I would use cast(char*)myString.ptr. If it is a D function, why does it not use const? Or for that matter, why does it not use char[]? -- Simen
Sep 11 2010
next sibling parent =?UTF-8?B?TWFyaXVzeiBHbGl3acWEc2tp?= <alienballance gmail.com> writes:
On 2010-09-11 15:13, Simen kjaeraas wrote:
 Why does the function expect a char*? If it is an external C function,
 and it might change the passed values, you should make a duplicate
 mutable string, or use char[] in lieu of string.

 If it is an external C function that will *not* change the passed
 values, and you have write access to the D headers to interface to C,
 use const char* instead. If no write access, I would use
 cast(char*)myString.ptr.

Yes, it's external C function and I can modify bindings (just bindings, not ABI). Now I'll trace back library which is interfacing to me and possibly fix bindings. You helped me already, thanks a lot. I can already go on (this language is so cool btw.).
Sep 11 2010
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I'm interfacing with Scintilla (C++), but it works in a different way.
It uses messages, which allows it to be linked with practically any
language. But I can still pass parameters to be modified by passing
the address of the variable instead (the wrapper takes care of that).

Although linking with C++ is difficult, having proper C linkage is a
great thing. There's a ton of libraries out there ready to be used
right now in D.

2010/9/11 Mariusz Gliwi=C5=84ski <alienballance gmail.com>:
 On 2010-09-11 15:13, Simen kjaeraas wrote:
 Why does the function expect a char*? If it is an external C function,
 and it might change the passed values, you should make a duplicate
 mutable string, or use char[] in lieu of string.

 If it is an external C function that will *not* change the passed
 values, and you have write access to the D headers to interface to C,
 use const char* instead. If no write access, I would use
 cast(char*)myString.ptr.

Yes, it's external C function and I can modify bindings (just bindings, n=

 ABI). Now I'll trace back library which is interfacing to me and possibly
 fix bindings.

 You helped me already, thanks a lot. I can already go on (this language i=

 so cool btw.).

Sep 11 2010
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
shd:
 I'm having a problem in passing a value to char* expecting function
 in D 2.0. Already tried:
 to!(char*)("my string");

A solution, maybe correct: import std.string: toStringz, indexOf; import std.c.string: strlen; import std.stdio: writeln; void main() { string s = "my string"; assert(indexOf(s, '\0') == -1); // useful char* p = cast(char*)toStringz(s); writeln(strlen(p)); } But keep in mind this string p is managed by the D GC. That cast to cast(char*) is not nice. There is no need to dup the string given to toStringz because it performs the dup internally (wasting a initialization of 'copy'), this is the cleaned up implementation of toStringz: const(char)* toStringz(string s) { char[] copy = new char[s.length + 1]; copy[0 .. s.length] = s; copy[s.length] = 0; return copy.ptr; } I don't know why it returns a const(char)* instead of a char*. Do you know why? Bye, bearophile
Sep 11 2010
parent reply Jonathan M Davis <jmdavisprog gmail.com> writes:
On Saturday 11 September 2010 09:07:38 bearophile wrote:
 I don't know why it returns a const(char)* instead of a char*. Do you know
 why?
 
 Bye,
 bearophile

Well, if you look at toStringz()'s implementation, you may notice that there's commented out code which would not make a copy if there's a 0 in memory one passed the end of the string. It would simply use that 0 as the end of the const char* and avoid the copy. That being the case, it avoids a copy but must be const, because the string is immutable. Now, why that code is commented out, I don't know, and if toStringz() continues to always copy the string, then char* would likely be a better choice. But it could be that whatever issue made it so that the non-copying version was commented out will be fixed at some point, and toStringz() will once again cease to make a copy if it doesn't have to, at which point it would need to return const. - Jonathan M Davis
Sep 11 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Jonathan M Davis:
 Well, if you look at toStringz()'s implementation, you may notice that there's 
 commented out code which would not make a copy if there's a 0 in memory one 
 passed the end of the string. It would simply use that 0 as the end of the
const 
 char* and avoid the copy. That being the case, it avoids a copy but must be 
 const, because the string is immutable.

I see, thank you for the answer. Generally in the C code that uses the C string I can't be certain that it doesn't modify the string. On the other hand often I need a char* and not a const char*. Ao I'd like toStringz() to always copy and return a char* (Often I need a const pointer to mutable chars). Another possibility is to have two functions, one that always performs the copy and returns a char*, and one that sometimes doesn't copy and returns a const char*. Or a single template function that returns a const char* if doconst is true :-) auto toStringz(bool doconst=false)(string s) { ... Bye, bearophile
Sep 12 2010
prev sibling parent klickverbot <see klickverbot.at> writes:
On 9/11/10 3:00 PM, shd wrote:
 Hello,
 I'm having a problem in passing a value to char* expecting function
 in D 2.0. Already tried:

 to!(char*)("my string");

 but it seems like there (Phobos) is no template like this. Then,
 tried:

 cast(char*)to!(char[])("my string")

 which looked ok, but i think it's not a proper way to do that. Most
 strings converted this way works properly, but once:

 char* string1 = cast(char*)to!(char[])("my string 1");
 char* string2 = cast(char*)to!(char[])("my string 2");

 resulted:
 string1 = "my string 1"
 string2 = "my string 1my string 2"

 I can't manage this problem, could You hint me?

Use std.string.toStringz to convert a D string to a C null-terminated one. This asymmetry (no to!(char*)(string)) has been discussed once, but I can't remember the reason why it was not implemented right now.
Sep 14 2010