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.

Reply via email to