January 20, 2018
On Saturday, 20 January 2018 at 04:09:01 UTC, Joe wrote:
>    extern(C) char * [2] pvs;
>    foreach (i, val; paramValues)
>        pvs[i] = cast(char *)toStringz(val);
>
> And then use "cast(const char **)pvs" for the paramValues argument.

A slight improvement here that removes the need for any casts (and the extern(C) is useless here btw) is to just define it as const(char)*:

    const(char) * [2] pvs;
    foreach (i, val; paramValues)
        pvs[i] = toStringz(val);

Then you can call the argument with plain `pvs.ptr` instead of casting it. Though, make sure you remember the null at the end too!

> 1. Is malloc() the only way to allocate the arrays, either of Oid's, int's or char *'s, for passing to the libpq functions?  IOW, isn't there a way to take advantage of D's 'new' (and thus the GC)?

const(char)*[] pvs = new const(char)*[](size_here);
// could also have been `auto pvs = ...;` btw

// then still pass it to pqFunc(pvs.ptr)
// the .ptr gets the char** out of it.


Just double check the documentation of any C function you pass it to to make sure it doesn't explicitly say you must malloc it. Some C functions will try to free() the pointer you pass it, or may hold on to it. D's GC can't see pointers C functions keep, so  it might try to free that array any time after the local variable `pvs` in D goes out of scope.


> 2. How to convert a slice of Oid's or int's to an array of pointers suitable by processing by the libpq C function?

Same as above. The general pattern is:

C_Type[] name = new C_Type[](requested_size);
// pass as `name.ptr`. This becomes a C_Type*


Just again, remember requested_size needs to include the null terminator when C requires it, so a +1 might be helpful.

And also, no need for extern(C). That's more for function declarations/pointers or maybe global variables C needs to be able to see.

> But I'm not sure if it's really working (when I mistakenly had a * in the pts declaration, at one point it also seemed to work).

Oh yikes, that would have been undefined behavior there. So [x] on a pointer will just access memory past it - just like in C - and might sometimes work, might sometimes overwrite other memory (in your case, it probably overwrote some other local variable on the stack), or, best case scenario really, might cause a segmentation fault or access violation.
January 20, 2018
On Saturday, 20 January 2018 at 04:54:47 UTC, Adam D. Ruppe wrote:
> Same as above. The general pattern is:
>
> C_Type[] name = new C_Type[](requested_size);
> // pass as `name.ptr`. This becomes a C_Type*

Thanks, Adam. Perhaps something like this ought to make its way into the "D for C Programmers" page.
1 2
Next ›   Last »