Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
December 31, 2014 Passing string literals to C | ||||
---|---|---|---|---|
| ||||
What's best practice here? D strings are not null-terminated. char* cpling(char *s) { So toString("This i |
December 31, 2014 Re: Passing string literals to C | ||||
---|---|---|---|---|
| ||||
Posted in reply to Laeeth Isharc | Argh - no way to edit. What's best practice here? D strings are not null-terminated. === cpling.c char* cpling(char *s) { s[0]='!'; return s; } === dcaller.d extern(C) char* cpling(char* s); void callC() { writefln("%s",fromStringz(cpling("hello\0"))); } or void callC() { writefln("%s",fromStringz(cpling(toStringz("hello")))); } === am I missing a better way to do this? |
December 31, 2014 Re: Passing string literals to C | ||||
---|---|---|---|---|
| ||||
Posted in reply to Laeeth Isharc | V Wed, 31 Dec 2014 11:19:35 +0000 Laeeth Isharc via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> napsáno: > Argh - no way to edit. > > What's best practice here? > > D strings are not null-terminated. > === > cpling.c > > char* cpling(char *s) > { > s[0]='!'; > return s; > } > === > dcaller.d > > extern(C) char* cpling(char* s); > > void callC() > { > writefln("%s",fromStringz(cpling("hello\0"))); > } > > or > > void callC() > { > writefln("%s",fromStringz(cpling(toStringz("hello")))); > } > > === > > am I missing a better way to do this? First I am not sure, but you do not need to call fromStringz in this case. Next in this example you even not need to call toStringz, because D string literals are null-terminated. But generally it is better to use toStringz when need pass D strings to C code. Important Note: When passing a char* to a C function, and the C function keeps it around for any reason, make sure that you keep a reference to it in your D code. Otherwise, it may go away during a garbage collection cycle and cause a nasty bug when the C code tries to use it. |
December 31, 2014 Re: Passing string literals to C | ||||
---|---|---|---|---|
| ||||
Posted in reply to Laeeth Isharc | On 12/31/2014 8:19 PM, Laeeth Isharc wrote:
> Argh - no way to edit.
>
> What's best practice here?
>
> D strings are not null-terminated.
> ===
> cpling.c
>
> char* cpling(char *s)
> {
> s[0]='!';
> return s;
> }
> ===
> dcaller.d
>
> extern(C) char* cpling(char* s);
>
> void callC()
> {
> writefln("%s",fromStringz(cpling("hello\0")));
> }
>
> or
>
> void callC()
> {
> writefln("%s",fromStringz(cpling(toStringz("hello"))));
> }
>
> ===
>
> am I missing a better way to do this?
String literals are always null-terminated. You can typically pass them as-is and D will do the right thing (you can also pass "MyStr".ptr if you want). Use toStringz when the string came from an external source (read from a file, passed into a function and so on), since you can't be sure if it was a literal or not. toStringz will recognize if it has a null-terminator and will not do anything if it does.
Also, you should make sure to consider std.conv.to on any C strings returned into D if you are going to keep them around. fromStringz only creates a slice, which is fine for how you use it here, but could get you into trouble if you aren't careful. std.conv.to will allocate a new string.
|
December 31, 2014 Re: Passing string literals to C | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | On Wednesday, 31 December 2014 at 11:45:33 UTC, Mike Parker wrote:
> On 12/31/2014 8:19 PM, Laeeth Isharc wrote:
>> Argh - no way to edit.
>>
>> What's best practice here?
>>
>> D strings are not null-terminated.
>> ===
>> cpling.c
>>
>> char* cpling(char *s)
>> {
>> s[0]='!';
>> return s;
>> }
>> ===
>> dcaller.d
>>
>> extern(C) char* cpling(char* s);
>>
>> void callC()
>> {
>> writefln("%s",fromStringz(cpling("hello\0")));
>> }
>>
>> or
>>
>> void callC()
>> {
>> writefln("%s",fromStringz(cpling(toStringz("hello"))));
>> }
>>
>> ===
>>
>> am I missing a better way to do this?
>
> String literals are always null-terminated. You can typically pass them as-is and D will do the right thing (you can also pass "MyStr".ptr if you want).
String literals can implicitly convert to const(char)* or immutable(char)*. Neat. It doesn't appear to apply to array literals in general though...
|
December 31, 2014 Re: Passing string literals to C | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | On Wednesday, 31 December 2014 at 12:25:45 UTC, John Colvin wrote:
> String literals can implicitly convert to const(char)* or immutable(char)*. Neat. It doesn't appear to apply to array literals in general though...
I believe this is a special case specifically for strings added for convenience when interfacing with C. Walter has said that he is strongly against arrays decaying to points a la C, and D generally does not support it save for this special case.
|
December 31, 2014 Re: Passing string literals to C | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | Thanks for the help. Laeeth |
January 01, 2015 Re: Passing string literals to C | ||||
---|---|---|---|---|
| ||||
Posted in reply to Laeeth Isharc | On Wednesday, 31 December 2014 at 11:19:36 UTC, Laeeth Isharc wrote:
> Argh - no way to edit.
>
> What's best practice here?
>
> D strings are not null-terminated.
> ===
> cpling.c
>
> char* cpling(char *s)
> {
> s[0]='!';
> return s;
> }
> ===
> dcaller.d
>
> extern(C) char* cpling(char* s);
>
> void callC()
> {
> writefln("%s",fromStringz(cpling("hello\0")));
> }
>
> or
>
> void callC()
> {
> writefln("%s",fromStringz(cpling(toStringz("hello"))));
> }
>
> ===
>
> am I missing a better way to do this?
To call a C function you can either use string literals which are always null terminated or use std.string.toStringz (when using string variables) to add the null and return a char*.
To convert from char* (from a C function return value) to a D string use std.conv.to!(string).
|
Copyright © 1999-2021 by the D Language Foundation