vonKingsley
vonKingsley

Reputation: 33

Crystal-Lang C-Binding struct doesn't seem to pass null value

I'm currently trying to add c14n support for crystal-lang using a c-binding with libxml2. I've successfully been able to use xmlC14NDocSave to save the canonical xml to a file. The problem I'm having is with the xmlOutputBufferPtr for both xmlC14NDocSaveTo and xmlC14NExecute.

The error I receive is (Mac and Linux)

xmlC14NExecute: output buffer encoder != NULL but C14N requires UTF8 output

The documentation states

this buffer MUST have encoder==NULL because C14N requires UTF-8 output

in src/C14N/lib_C14N.cr I have the following code

type CharEncodingHandler = Void*
type Buff = Void*
#type OutputBuffer = Void*
struct OutputBuffer
  context : Void*
  writecallback : OutputWriteCallback
  closecallback : OutputCloseCallback
  encoder : CharEncodingHandler
  buffer  : Buff
  conv    : Buff
  written : Int32
  error   : Int32
end
....
fun xmlC14NDocSaveTo(doc : LibXML::Node*, nodes : LibXML::NodeSet*, mode : Mode, inclusive_ns_prefixes : UInt8**, with_comments : Int32, buf : OutputBuffer*) : Int32
fun xmlC14NExecute(doc : LibXML::Node*, is_visible_callback : IsVisibleCallback, user_data : Void*, mode : Mode, inclusive_ns_prefixes : UInt8**, with_comments : Int32, buf : OutputBuffer*) : Int32

In src/C14N.cr

output = XML::LibC14N::OutputBuffer.new
p output.encoder
XML::LibC14N.xmlC14NDocSaveTo(@xml, nil, @mode, nil, 0, out output)

The results of the p ouput.encoder are Pointer(Void).null so It appears the value is null.

The c14n.c function is just checking null on the buf->encoder struct

if (buf->encoder != NULL) {
    xmlGenericError(xmlGenericErrorContext,
                    "xmlC14NExecute: output buffer encoder != NULL but C14N requires UTF8 output\n");
    return (-1);
}

Any help would be appreciated, the code can be found on my github account. clone and run crystal spec

Upvotes: 2

Views: 383

Answers (1)

Jonne Haß
Jonne Haß

Reputation: 4857

Don't specify out output, that simply reserves a block of memory of the size of the struct on the stack and passes a pointer to it. As of Crystal 0.7.6 it's not zeroed it out, so you pass garbage.

Using output = XML::LibC14N::OutputBuffer.new is already the first right step, since that does zero out the memory. Now to pass it, simply replace out output with pointerof(output).

Upvotes: 1

Related Questions