Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
March 23, 2012 string[] to char** | ||||
---|---|---|---|---|
| ||||
What's the best way to convert char** from string[]? |
March 23, 2012 Re: string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to simendsjo | On Friday, 23 March 2012 at 15:48:12 UTC, simendsjo wrote: > What's the best way to convert char** from string[]? This is one way to do it: import std.algorithm, std.array, std.string, core.stdc.stdio; void main() { auto data = ["red", "yellow", "green"]; immutable(char)** p = array(map!toStringz(data)).ptr; printf("%s %s %s\n", p[0], p[1], p[2]); } Note: the pointer array is managed by the D GC. With DMD 2.059: immutable(char)** p = data.map!toStringz().array().ptr; Bye, bearophile |
March 23, 2012 Re: string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to simendsjo | On 03/23/2012 08:48 AM, simendsjo wrote: > What's the best way to convert char** from string[]? In C, char** communicates transfer of ownership. Is that what you are trying to do? Are you going to pass a slice to a C function to be filled in by that C function? Such functions usually assign to *str. In that case you can use the "make slice from raw pointer" method below. I hope others will answer my concern in the comment below: import std.stdio; import std.c.stdlib; import std.c.string; void C_func_with_an_out_parameter(char ** str) { *str = cast(char*)calloc(1, 10); (*str)[0] = 'A'; (*str)[1] = '\0'; } void main() { char * p; C_func_with_an_out_parameter(&p); char[] slice = p[0..strlen(p)]; // <-- make a D slice /* * Note: I don't think that the memory that * std.stdlib.calloc() returns is managed by the GC. For * that reason, I don't think it will be safe to share the * element with another slice and expect normal behavior * of element-sharing between slices. * * In other words, this would be risky: * * char[] anotherSlice = slice; */ writeln(slice); free(p); } Ali |
March 23, 2012 Re: string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On 03/23/2012 11:23 AM, Ali Çehreli wrote:
> On 03/23/2012 08:48 AM, simendsjo wrote:
> > What's the best way to convert char** from string[]?
>
> In C, char** communicates transfer of ownership.
Ok, I once again misunderstood the question. :( My question in the comment remains.
Thank you,
Ali
|
March 23, 2012 Re: string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 3/23/12, bearophile <bearophileHUGS@lycos.com> wrote:
> This is one way to do it:
> immutable(char)** p = array(map!toStringz(data)).ptr;
This is asked so frequently that I think we could consider adding it to Phobos.
|
March 24, 2012 Re: string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Fri, 23 Mar 2012 19:23:07 +0100, Ali Çehreli <acehreli@yahoo.com> wrote:
> On 03/23/2012 08:48 AM, simendsjo wrote:
> > What's the best way to convert char** from string[]?
>
> In C, char** communicates transfer of ownership. Is that what you are trying to do? Are you going to pass a slice to a C function to be filled in by that C function?
>
> Such functions usually assign to *str. In that case you can use the "make slice from raw pointer" method below. I hope others will answer my concern in the comment below:
>
> import std.stdio;
> import std.c.stdlib;
> import std.c.string;
>
> void C_func_with_an_out_parameter(char ** str)
> {
> *str = cast(char*)calloc(1, 10);
> (*str)[0] = 'A';
> (*str)[1] = '\0';
> }
>
> void main()
> {
> char * p;
> C_func_with_an_out_parameter(&p);
>
> char[] slice = p[0..strlen(p)]; // <-- make a D slice
>
> /*
> * Note: I don't think that the memory that
> * std.stdlib.calloc() returns is managed by the GC. For
> * that reason, I don't think it will be safe to share the
> * element with another slice and expect normal behavior
> * of element-sharing between slices.
> *
> * In other words, this would be risky:
> *
> * char[] anotherSlice = slice;
> */
> writeln(slice);
>
> free(p);
> }
>
> Ali
I'm not sure of the semantics of the function yet. Don't know if it copies the argument or stores it, if it frees it or expects me to free it :|
But it's not filling the array.
|
March 24, 2012 Re: string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Fri, 23 Mar 2012 17:09:18 +0100, bearophile <bearophileHUGS@lycos.com> wrote: > On Friday, 23 March 2012 at 15:48:12 UTC, simendsjo wrote: >> What's the best way to convert char** from string[]? > > This is one way to do it: > > > import std.algorithm, std.array, std.string, core.stdc.stdio; > void main() { > auto data = ["red", "yellow", "green"]; > immutable(char)** p = array(map!toStringz(data)).ptr; > printf("%s %s %s\n", p[0], p[1], p[2]); > } > > > Note: the pointer array is managed by the D GC. > > With DMD 2.059: > > immutable(char)** p = data.map!toStringz().array().ptr; > > Bye, > bearophile Thanks. A lot shorter and safer than my current approach. I also expect toStringz doesn't make a copy if \0 is at the end. For reference, my current approach was: auto strings = ["a", "b"]; auto c_strings = cast(char**)malloc((char*).sizeof * strings.length); for(int i; i < strings.length; i++) c_strings[i] = strings[i].ptr; |
March 24, 2012 Re: string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to simendsjo | On Sat, 24 Mar 2012 11:41:48 +0100, simendsjo <simendsjo@gmail.com> wrote: > On Fri, 23 Mar 2012 17:09:18 +0100, bearophile <bearophileHUGS@lycos.com> wrote: > >> On Friday, 23 March 2012 at 15:48:12 UTC, simendsjo wrote: >>> What's the best way to convert char** from string[]? >> >> This is one way to do it: >> >> >> import std.algorithm, std.array, std.string, core.stdc.stdio; >> void main() { >> auto data = ["red", "yellow", "green"]; >> immutable(char)** p = array(map!toStringz(data)).ptr; >> printf("%s %s %s\n", p[0], p[1], p[2]); >> } >> >> >> Note: the pointer array is managed by the D GC. >> >> With DMD 2.059: >> >> immutable(char)** p = data.map!toStringz().array().ptr; >> >> Bye, >> bearophile > > Thanks. A lot shorter and safer than my current approach. I also expect toStringz doesn't make a copy if \0 is at the end. > > For reference, my current approach was: > > auto strings = ["a", "b"]; > auto c_strings = cast(char**)malloc((char*).sizeof * strings.length); > for(int i; i < strings.length; i++) > c_strings[i] = strings[i].ptr; Oh, I didn't find toStringz, so I turned it into: auto c_strings = strings.map!(toUTFz!(char*)).array().ptr; |
March 24, 2012 Re: string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On Fri, 23 Mar 2012 22:42:08 +0100, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> On 3/23/12, bearophile <bearophileHUGS@lycos.com> wrote:
>> This is one way to do it:
>> immutable(char)** p = array(map!toStringz(data)).ptr;
>
> This is asked so frequently that I think we could consider adding it to Phobos.
Yes. The first thing I tried was to!(char**)(strings), but that didn't work
|
March 24, 2012 Re: string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to simendsjo | simendsjo: > Oh, I didn't find toStringz, so I turned it into: It's in std.string. > auto c_strings = strings.map!(toUTFz!(char*)).array().ptr; That's wrong syntax, that 2.059head doesn't enforce yet, map needs an ending (). Bye, bearophile |
Copyright © 1999-2021 by the D Language Foundation