I am trying to handle errors when calling this method and getting the error message from the errstr pointer.
@handle = LibRdKafka.kafka_new(LibRdKafka::TYPE_CONSUMER, conf, out errstr, 128)
raise "Kafka: Unable to create new consumer: #{errstr}" unless errstr == LibRdKafka::OK
I am getting the following output:
Program hit a breakpoint and no debugger was attached
I’m unsure why the exception isn’t getting raised. Along with this, I am unsure how to convert the errstr : UInt8* into a Crystal String. Can anyone help me with this?
I think you’re misinterpreting the API. errstr receives a pointer to previously allocated memory and rd_kafka_new will write to that memory.
The out keyword does not work for this. It just allocates space for a single UInt8 on the stack because the parameter type is UInt8*.
But you need a much larger size and out cannot know that because the size is dynamic, i.e. not encoded in the type.
Also, if i am reading things correctly, the docs says that the error condition is if the return value @handle is null. And you are checking the out value instead of the return value
Thank you @straight-shoota for the detailed explanation and thanks @bcardiff yes you are right. It works now, here is the full working solution for anyone else struggling with something similar:
error_buffer = uninitialized UInt8[128]
errstr = error_buffer.to_unsafe
@handle = LibRdKafka.kafka_new(LibRdKafka::TYPE_CONSUMER, conf, errstr, error_buffer.size)
raise "Unable to create new consumer: #{String.new(errstr)}" if @handle.null?
Yeah there’s a few around, but most of them are archived and the API of them isn’t as simple as I think it could be. I like the API of this one but it has no tests and has some small issues - so I’m forking it