Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
June 04, 2013 Convert string[] to char** | ||||
---|---|---|---|---|
| ||||
Attachments:
| 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 |
June 04, 2013 Re: Convert string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bruce Smith | 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 |
June 04, 2013 Re: Convert string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | 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
|
June 04, 2013 Re: Convert string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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 |
June 04, 2013 Re: Convert string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | 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. > |
June 04, 2013 Re: Convert string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bruce Smith | 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:
>> On 2013-06-04 12:41, bearophile wrote:
>>
>>> An alternative is something like (untested):
>>>
>>> auto ckeys = mykeys.map!toStringz.array;
>>
>> Right, that should work.
>>
>
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).array
|
June 04, 2013 Re: Convert string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to David | David:
> mykeys.map!(x => x.dup.toStringz).array
Is toStringz already dup-ping the buffer?
Bye,
bearophile
|
June 04, 2013 Re: Convert string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Tuesday, 4 June 2013 at 12:20:24 UTC, bearophile wrote:
> David:
>
>> mykeys.map!(x => x.dup.toStringz).array
>
> Is toStringz already dup-ping the buffer?
Not necessarily. IIRC, if the string already has a null terminator then it just returns the string ptr. Only dups if it needs to.
|
June 04, 2013 Re: Convert string[] to char** | ||||
---|---|---|---|---|
| ||||
Posted in reply to David | 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:
>>> On 2013-06-04 12:41, bearophile wrote:
>>>
>>>> An alternative is something like (untested):
>>>>
>>>> auto ckeys = mykeys.map!toStringz.array;
>>> Right, that should work.
>>>
> 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).array
>
>
|
Copyright © 1999-2021 by the D Language Foundation