How to Deify char**

ag0aep6g via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue May 17 13:23:39 PDT 2016


On 05/17/2016 09:37 PM, WhatMeWorry wrote:
> I'm weak enough with C pointers, but when I see char** my brain freezes
> up like a deer caught in headlights. Can anyone translate the below C
> call into D?

First things first: char** is a perfectly fine D type, of course. But 
you probably know that.

> ALURE_API const ALCchar** ALURE_APIENTRY alureGetDeviceNames(ALCboolean
> all,ALCsizei *count)
>
> // my poor attempt to Deify it
>
> int count;
> const char[][] allDevice = alureGetDeviceNames(true, &count);

char[][] is quite different from char**. While you can make a char[] 
from a char* by slicing the pointer, you can't make a char[][] from a 
char** in the same way, because the element type changes.

You need to make the char* -> char[] conversions individually and fill a 
new array with them:

----
import std.stdio: writeln;
import std.string: fromStringz;

void main()
{
     /* Step 1: Get the char** and the count. */
     int count;
     char** pp = alureGetDeviceNames(&count);

     /* Step 2: char** + count -> char*[] */
     char*[] pa = pp[0 .. count];

     /* Step 3: Iterate over the char*[] and convert the elements
     to char[]. Fill a newly allocated char[][] with them. */
     char[][] aa = new char[][](count);
     foreach (i, p; pa)
     {
         char[] a = fromStringz(p); /* char* -> char[] */
         aa[i] = a;
     }

     /* print to verify */
     writeln(aa); /* ["foo", "bar", "baz"] */
}

char** alureGetDeviceNames(int* count)
{
     /* just some test data */
     *count = 3;
     return ["foo\0".dup.ptr, "bar\0".dup.ptr, "baz\0".dup.ptr].ptr;
}
----

Note that this allocates a new array. Depending on the exact scenario, 
it may be worthwhile to stop at the char*[] stage instead, and work with 
null terminated strings.


More information about the Digitalmars-d-learn mailing list