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.