[racket] Problems wrapping the RabbitMQ C client library using the ffi

From: Juan Garcia (thejuangarcia at googlemail.com)
Date: Sun Aug 26 13:10:18 EDT 2012

Hi,

I'm having a problem wrapping the Rabbit MQ C client
library (https://github.com/alanxz/rabbitmq-c) using the ffi.  My
problem is with the amqp_queue_declare function.  The C
declaration is:

amqp_queue_declare_ok_t *
amqp_queue_declare(amqp_connection_state_t state,
                   amqp_channel_t channel,
                   amqp_bytes_t queue,
                   amqp_boolean_t passive,
                   amqp_boolean_t durable,
                   amqp_boolean_t exclusive,
                   amqp_boolean_t auto_delete,
                   amqp_table_t arguments);

It seems to run successfully when wrapped to return an opaque
pointer:

(define _amqp-queue-declare-ok-pointer (_cpointer 'QUEUE-DECLARE-OK))

(define-amqp amqp_queue_declare
  (_fun _amqp-connection-state-pointer
        _amqp_channel_t _pointer _int _int _int _int _pointer
        -> _amqp-queue-declare-ok-pointer))

> #<cpointer:QUEUE-DECLARE-OK>

Wrapping it to return a cstruct pointer fails with a SEGV.

> SIGSEGV MAPERR si_code 1 fault on addr (nil)

The wrapping code for the c structs is as follows:

(define _size_t _uint32)
(define _amqp_channel_t _uint16)

(define-cstruct _amqp_bytes_t
  ([len _size_t]
   [bytes _pointer]))

;; c definition of amqp_bytes_t is:
;; typedef struct amqp_bytes_t_ {
;;   size_t len;
;;   void *bytes;
;; } amqp_bytes_t;

(define-cstruct _amqp_queue_declare_ok_t
  ([queue _amqp_bytes_t]
   [message_count _uint32]
   [consumer_count _uint32]))

;; typedef struct amqp_queue_declare_ok_t_ {
;;   amqp_bytes_t queue;
;;   uint32_t message_count;
;;   uint32_t consumer_count;
;; } amqp_queue_declare_ok_t;

(define-amqp amqp_queue_declare
  (_fun _amqp-connection-state-pointer
        _amqp_channel_t _pointer _int _int _int _int _pointer
        -> _amqp_queue_declare_ok_t))

Any ideas what I'm doing wrong here?

The full code so far is below:

#lang racket/base

(require ffi/unsafe
         ffi/unsafe/define)

(define lib-rabbit-mq (ffi-lib "librabbitmq"))
(define-ffi-definer define-amqp lib-rabbit-mq)

;; C types

(define _size_t _uint32)
(define _amqp_channel_t _uint16)

(define-cstruct _amqp_bytes_t
  ([len _size_t]
   [bytes _pointer]))

(define-cstruct _amqp_queue_declare_ok_t
  ([queue _amqp_bytes_t]
   [message_count _uint32]
   [consumer_count _uint32]))

(define-cstruct _amqp_method_t
  ([id _uint32]
   [decoded _pointer]))

(define-cstruct _amqp_rpc_reply_t
  ([reply_type _int]
   [reply _amqp_method_t]
   [library_error _int]))

(define _amqp-connection-state-pointer (_cpointer 'CONNECTION-STATE))
(define _amqp-channel-open_ok-pointer (_cpointer 'CHANNEL-OPEN-OK))

;; C functions

(define-amqp amqp_error_string (_fun _int -> _string))
(define-amqp amqp_get_rpc_reply (_fun _amqp-connection-state-pointer ->
                                      _amqp_rpc_reply_t))

(define-amqp amqp_new_connection (_fun -> _amqp-connection-state-pointer))
(define-amqp amqp_open_socket (_fun _string _int -> _int))
(define-amqp amqp_set_sockfd (_fun _amqp-connection-state-pointer
                                   _int -> _int))
(define-amqp amqp_login (_fun _amqp-connection-state-pointer
                              _string _int _int _int _int _string _string ->
                              _amqp_rpc_reply_t))
(define-amqp amqp_channel_open (_fun _amqp-connection-state-pointer
                                     _amqp_channel_t ->
                                     _amqp-channel-open_ok-pointer))

;; *** THIS DOES NOT WORK

(define-amqp amqp_queue_declare
  (_fun _amqp-connection-state-pointer
        _amqp_channel_t _pointer _int _int _int _int _pointer
        -> _amqp_queue_declare_ok_t))

;; *** THIS SEEMS TO WORK

(define _amqp-queue-declare-ok-pointer (_cpointer 'QUEUE-DECLARE-OK))

(define-amqp amqp_queue_declare
  (_fun _amqp-connection-state-pointer
        _amqp_channel_t _pointer _int _int _int _int _pointer
        -> _amqp-queue-declare-ok-pointer))

;; main

(define conn (amqp_new_connection))
(define sockfd (amqp_open_socket "localhost" 5672))
(when (< sockfd 0) (amqp_error_string (* -1 sockfd)))
(amqp_set_sockfd conn sockfd)
(define *AMQP_SASL_METHOD_PLAIN* 0)
(define resp (amqp_login conn "/" 0 131072 0
                         *AMQP_SASL_METHOD_PLAIN* "user" "pwd"))

(amqp_channel_open conn 1)
(amqp_queue_declare conn 1 #f 0 0 0 1 #f)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20120826/2133a5e3/attachment.html>

Posted on the users mailing list.