digitalmars.D - Convert string[] to char**
- Bruce Smith (16/16) Jun 04 2013 Hello
- Jacob Carlborg (11/26) Jun 04 2013 I think you need to do something like:
- bearophile (5/13) Jun 04 2013 An alternative is something like (untested):
- Jacob Carlborg (4/6) Jun 04 2013 Right, that should work.
- Bruce Smith (11/16) Jun 04 2013 Thank you Jacob and bearophile ... just had to add a cast to get rid of
- David (6/32) Jun 04 2013 Casting it isn't the best way here, you shouldn't cast immutability
- bearophile (4/5) Jun 04 2013 Is toStringz already dup-ping the buffer?
- Peter Alexander (4/7) Jun 04 2013 Not necessarily. IIRC, if the string already has a null
- Bruce Smith (7/37) Jun 04 2013 The C function's signature is determined by the library from which it
Hello /[I'll prefix this question by stating that I am not a strong C programmer; my long experience is in a wide range of languages other than C//]/ I wish to call some functions in a complex C library from D. Since this a large & complex library, I've wrapped a bunch of the functions using SWIG (swig -d -d2 ...). One of the C functions has a signature like: void foo(const char * const *keys); SWIG has given me a D function signature like: void foo(char** keys); In my D program it is natural to represent some keys as an array of strings, for example: string[] mykeys; How should I convert mykeys from string[] to char** so that I can call foo with mykeys as the actual parameter? Regards
Jun 04 2013
On 2013-06-04 09:18, Bruce Smith wrote:Hello /[I'll prefix this question by stating that I am not a strong C programmer; my long experience is in a wide range of languages other than C//]/ I wish to call some functions in a complex C library from D. Since this a large & complex library, I've wrapped a bunch of the functions using SWIG (swig -d -d2 ...). One of the C functions has a signature like: void foo(const char * const *keys); SWIG has given me a D function signature like: void foo(char** keys); In my D program it is natural to represent some keys as an array of strings, for example: string[] mykeys; How should I convert mykeys from string[] to char** so that I can call foo with mykeys as the actual parameter?I think you need to do something like: import std.conv; string[] mykeys; char*[] ckeys; ckeys.reserve(mykeys.length); foreach (key ; mykeys) ckeys ~= to!(char*)(key); foo(ckeys.ptr); -- /Jacob Carlborg
Jun 04 2013
Jacob Carlborg:I think you need to do something like: import std.conv; string[] mykeys; char*[] ckeys; ckeys.reserve(mykeys.length); foreach (key ; mykeys) ckeys ~= to!(char*)(key); foo(ckeys.ptr);An alternative is something like (untested): auto ckeys = mykeys.map!toStringz.array; Bye, bearophile
Jun 04 2013
On 2013-06-04 12:41, bearophile wrote:An alternative is something like (untested): auto ckeys = mykeys.map!toStringz.array;Right, that should work. -- /Jacob Carlborg
Jun 04 2013
Thank you Jacob and bearophile ... just had to add a cast to get rid of immutable from your suggestion. For completeness, this compiles under 2.063: void foo(char** k) { // body } string[] mykeys; auto ckeys = cast(char**)mykeys.map!toStringz.array; foo(ckeys); Bruce On 04/06/13 20:59, Jacob Carlborg wrote:On 2013-06-04 12:41, bearophile wrote:An alternative is something like (untested): auto ckeys = mykeys.map!toStringz.array;Right, that should work.
Jun 04 2013
Am 04.06.2013 13:49, schrieb Bruce Smith:Thank you Jacob and bearophile ... just had to add a cast to get rid of immutable from your suggestion. For completeness, this compiles under 2.063: void foo(char** k) { // body } string[] mykeys; auto ckeys = cast(char**)mykeys.map!toStringz.array; foo(ckeys); Bruce On 04/06/13 20:59, Jacob Carlborg wrote:Casting it isn't the best way here, you shouldn't cast immutability away, make sure your function does not mutate it (it must not!) then you could change the function signature to const(void*)*, otherwise use char[] instead of string, this should do it: mykeys.map!(x => x.dup.toStringz).arrayOn 2013-06-04 12:41, bearophile wrote:An alternative is something like (untested): auto ckeys = mykeys.map!toStringz.array;Right, that should work.
Jun 04 2013
David:mykeys.map!(x => x.dup.toStringz).arrayIs toStringz already dup-ping the buffer? Bye, bearophile
Jun 04 2013
On Tuesday, 4 June 2013 at 12:20:24 UTC, bearophile wrote:David:Not necessarily. IIRC, if the string already has a null terminator then it just returns the string ptr. Only dups if it needs to.mykeys.map!(x => x.dup.toStringz).arrayIs toStringz already dup-ping the buffer?
Jun 04 2013
The C function's signature is determined by the library from which it originates; the D signature created by SWIG is tied to the C original; therefore I can't alter the fact that the parameter is of type char** (i.e. it is mutable). OTOH, toStringz produces an immutable string. Bruce On 04/06/13 22:07, David wrote:Am 04.06.2013 13:49, schrieb Bruce Smith:Thank you Jacob and bearophile ... just had to add a cast to get rid of immutable from your suggestion. For completeness, this compiles under 2.063: void foo(char** k) { // body } string[] mykeys; auto ckeys = cast(char**)mykeys.map!toStringz.array; foo(ckeys); Bruce On 04/06/13 20:59, Jacob Carlborg wrote:Casting it isn't the best way here, you shouldn't cast immutability away, make sure your function does not mutate it (it must not!) then you could change the function signature to const(void*)*, otherwise use char[] instead of string, this should do it: mykeys.map!(x => x.dup.toStringz).arrayOn 2013-06-04 12:41, bearophile wrote:An alternative is something like (untested): auto ckeys = mykeys.map!toStringz.array;Right, that should work.
Jun 04 2013