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

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon Aug 27 10:39:07 EDT 2012

You need

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

Using `_amqp_queue_declare_ok_t' corresponds to the return type
`_amqp_queue_declare_ok_t', while `_amqp_queue_declare_ok_t-pointer'
corresponds to `_amqp_queue_declare_ok_t*'.

At Sun, 26 Aug 2012 18:10:18 +0100, Juan Garcia wrote:
> 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)
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users

Posted on the users mailing list.