Directly provide "const unsigned char **" using CGO

449 views
Skip to first unread message

aren...@gmail.com

unread,
Apr 1, 2016, 7:16:37 AM4/1/16
to golang-nuts
Hello,

I'm in the process of writing a wkhtmltox library wrapper. I got most parts working despite my small C experience.

My problem at the moment is retrieving the output PDF. Since I don't want to let the library write the PDF file into some kind of temp dir, I plan to use the wkhtmltopdf_get_output method[1].
This method writes the PDF data into a const unsigned char **

My question is: Is there a possibility to directly provide a fitting variable or do I need to write a C wrapper function that calls a exported Go method. I would like to minimize data copies.

Jan

[1] https://github.com/wkhtmltopdf/wkhtmltopdf/blob/master/src/lib/pdf.h#L75

Tamás Gulácsi

unread,
Apr 1, 2016, 8:47:59 AM4/1/16
to golang-nuts
AFAIK a **char means you have to allocate a void pointer and will get the *char's address in there. From there ön you can
var pdf []byte = *((*[1<<31]byte)(unsafe.Pointer(p)))

where p is the returned pointer.

James Bardin

unread,
Apr 1, 2016, 9:20:55 AM4/1/16
to golang-nuts


On Friday, April 1, 2016 at 8:47:59 AM UTC-4, Tamás Gulácsi wrote:
AFAIK a **char means you have to allocate a void pointer and will get the *char's address in there. From there ön you can
var pdf []byte = *((*[1<<31]byte)(unsafe.Pointer(p)))


This isn't a valid assignment, but you should also slice the array immediately so that you aren't left with out of bounds indexes

    pdf := (*(*[1<<31 - 1]byte)(unsafe.Pointer(p)))[:length:length]
 

aren...@gmail.com

unread,
Apr 1, 2016, 9:35:24 AM4/1/16
to golang-nuts
Thanks for your help, but this only helps with dereferencing a returned pointer. However, the C function takes a pointer that i need to provide.
Sorry i should have pointed that out more clearly. Here is the function definition:

CAPI(long) wkhtmltopdf_get_output(wkhtmltopdf_converter * converter, const unsigned char **);

James Bardin

unread,
Apr 1, 2016, 9:46:09 AM4/1/16
to golang-nuts, aren...@gmail.com


On Friday, April 1, 2016 at 9:35:24 AM UTC-4, aren...@gmail.com wrote:
Thanks for your help, but this only helps with dereferencing a returned pointer. However, the C function takes a pointer that i need to provide.
Sorry i should have pointed that out more clearly. Here is the function definition:

CAPI(long) wkhtmltopdf_get_output(wkhtmltopdf_converter * converter, const unsigned char **);



Give it a pointer to a nil pointer of the correct type:

var p *C.uchar
ret := wkhtmltopdf_get_output(converter, &p)

Bryan Matsuo

unread,
Apr 2, 2016, 4:00:19 AM4/2/16
to golang-nuts, aren...@gmail.com
In lmdb-go I have been making slices from using the reflect package.


I can't remember off the top of my head where I first saw that trick. But I  remember reading about a different project doing the same thing.

The [1<<31 - 1]byte trick is interesting though. I wonder if it is faster.

Tamás Gulácsi

unread,
Apr 2, 2016, 8:25:05 AM4/2/16
to golang-nuts
The reflect.SliceHeader solution is deprecated.

Bryan Matsuo

unread,
Apr 2, 2016, 4:18:54 PM4/2/16
to golang-nuts
On Saturday, April 2, 2016 at 5:25:05 AM UTC-7, Tamás Gulácsi wrote:
The reflect.SliceHeader solution is deprecated.

Can you please give a better explanation than that? Ideally one that has a link. I get tat the docs say it's unsafe, but to me it's not obviously less safe than the other conversion being discussed.

James Bardin

unread,
Apr 2, 2016, 4:41:00 PM4/2/16
to Bryan Matsuo, golang-nuts
I assume because the docs for the SliceHeader say: "[SliceHeader]
cannot be used safely or portably and its representation may change in
a later release.". Whereas the array-to-slice conversion happens
correctly and safely regardless.

https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices

Bryan Matsuo

unread,
Apr 2, 2016, 5:55:31 PM4/2/16
to golang-nuts, bryan....@gmail.com
Fair enough. I didn't really remember that warning from before.

So three sources provide 3 choices of "a very big array". Using 1<<31-1 would be the largest portable choice, right?
Reply all
Reply to author
Forward
0 new messages