internal MessageAndError?ConsumerPoll(IntPtr timeoutMs)
        {
            IntPtr msgPtr = LibRdKafka.consumer_poll(handle, timeoutMs);

            if (msgPtr == IntPtr.Zero)
            {
                return(null);
            }
            var msg = Marshal.PtrToStructure <rd_kafka_message>(msgPtr);

            byte[] payload = null;
            byte[] key     = null;
            if (msg.payload != IntPtr.Zero)
            {
                payload = new byte[(int)msg.len];
                Marshal.Copy(msg.payload, payload, 0, (int)msg.len);
            }
            if (msg.key != IntPtr.Zero)
            {
                key = new byte[(int)msg.key_len];
                Marshal.Copy(msg.key, key, 0, (int)msg.key_len);
            }
            string topic = null;

            if (msg.rkt != IntPtr.Zero)
            {
                topic = Marshal.PtrToStringAnsi(LibRdKafka.topic_name(msg.rkt));
            }
            LibRdKafka.message_destroy(msgPtr);

            var message = new Message()
            {
                Topic     = topic,
                Partition = msg.partition,
                Offset    = msg.offset,
                Payload   = payload,
                Key       = key
            };

            return(new MessageAndError()
            {
                Message = message,
                Error = msg.err
            });
        }