Search code examples
crystal-lang

Referencing C enums in a Crystal lib


I'm trying to write a Crystal wrapper around libevent, and I wondered how to approach its enums that are named as all lower-case, for instance:

enum ev_http_request_error:

I tried the following:

@[Link("event")]
lib LibEvent
  # <snip>
  enum evhttp_request_error
    EVREQ_HTTP_TIMEOUT,
    EVREQ_HTTP_EOF,
    EVREQ_HTTP_INVALID_HEADER,
    EVREQ_HTTP_BUFFER_ERROR,
    EVREQ_HTTP_DATA_TOO_LONG
  end
end

but this fails because evhttp_request_error doesn't fit the grammar for a Crystal constant. How should I address this?


Solution

  • You can name it whatever you want. But when you use enum inside your lib wrapper, you just declare a new C enum:

    @[Link("event")]
    lib LibEvent
       enum EvHTTPRequestError
         EVREQ_HTTP_TIMEOUT
         EVREQ_HTTP_EOF
         EVREQ_HTTP_INVALID_HEADER
         EVREQ_HTTP_BUFFER_ERROR
         EVREQ_HTTP_DATA_TOO_LONG
      end
    end
    

    This is effectively the same as:

    @[Link("event")]
    lib LibEvent
       enum EvHTTPRequestError
         EVREQ_HTTP_TIMEOUT = 0
         EVREQ_HTTP_EOF = 1
         EVREQ_HTTP_INVALID_HEADER = 2
         EVREQ_HTTP_BUFFER_ERROR = 3
         EVREQ_HTTP_DATA_TOO_LONG = 4
      end
    end
    

    and the values in this enum will not match the values from your original C lib.

    You need to set (duplicate) correct values manually in your enum.

    Since Crystal only binds to a shared library file, there is no option other than manually (sometimes automatically) duplicating these as constants in Crystal code.

    Checkout example in Crystal stdlib