Using Postgres connection functions

Adam D. Ruppe destructionator at gmail.com
Sat Jan 20 04:54:47 UTC 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.


More information about the Digitalmars-d-learn mailing list