[cffi-devel] First usages of CFFI

Marko Tapio Manninen mmstud at gmail.com
Tue Jun 17 00:59:12 UTC 2008


Hi,

so far i have compiled some programs, that use CFFI, but now id like  
to create my own.  As usual i counter my limits of knowledge and hope  
to find some answers here. I'm using libevent library (later doing  
same with libev), that has a simple event based server application,  
which i want to use from ccl / sbcl. I'll put two c functions first,  
and then some header information and finally some lisp code i have  
created. Im particularry interested getting some comments, how the  
work should be done. Yet there re two parts of the code, where i have  
stuck and they are:

void evhttp_set_gencb(struct evhttp *http, void (*cb)(struct  
evhttp_request *, void *), void *cbarg) {}

(defcfun ("evhttp_set_gencb" %evhttp-set-gencb) :void
	(http evhttp)
	???)

Actually same part occurs on evbuffer:

void (*cb)(struct evbuffer *, size_t, size_t, void *);

Regards,
-Marko

--------------------------------------------------------------------------------------------------------------------------------------

// ACTUAL APPLICATION

void generic_handler(struct evhttp_request *req, void *arg)
{
         struct evbuffer *buf;
         buf = evbuffer_new();

         if (buf == NULL)
             err(1, "failed to create response buffer");

         evbuffer_add_printf(buf, "Requested: %sn",  
evhttp_request_uri(req));
         evhttp_send_reply(req, HTTP_OK, "OK", buf);
}

int main(int argc, char **argv)
{
     struct evhttp *httpd;

     event_init();
     httpd = evhttp_start("0.0.0.0", 5007);

     /* Set a callback for requests to "/specific". */
     /* evhttp_set_cb(httpd, "/specific", another_handler, NULL); */

     /* Set a callback for all other requests. */
     evhttp_set_gencb(httpd, generic_handler, NULL);

     event_dispatch();

     /* Not reached in this code as it is now. */
     evhttp_free(httpd);

     return 0;
}

// SOME C CODE TO DEFINE

#define HTTP_OK 200

struct evhttp;

struct evhttp_request;

struct evbuffer {
	u_char *buffer;
	u_char *orig_buffer;

	size_t misalign;
	size_t totallen;
	size_t off;

	void (*cb)(struct evbuffer *, size_t, size_t, void *);
	void *cbarg;
};

struct event_base * event_init(void) {}

struct evhttp * evhttp_start(const char *address, u_short port) {}

void evhttp_free(struct evhttp* http) {}

void evhttp_set_gencb(struct evhttp *http, void (*cb)(struct  
evhttp_request *, void *), void *cbarg) {}

// LISP PART

(cffi:define-foreign-library libevent
	   (:darwin "libevent.dylib")
	   (t (:default "libevent")))

(cffi:use-foreign-library libevent)

(defconstant HTTP_OK 200)
(defconstant HTTP_NOCONTENT 204)
(defconstant HTTP_MOVEPERM 301)
(defconstant HTTP_MOVETEMP 302)
(defconstant HTTP_NOTMODIFIED 304)
(defconstant HTTP_BADREQUEST 400)
(defconstant HTTP_NOTFOUND 404)
(defconstant HTTP_SERVUNAVAIL 503)

(defctype size-t :unsigned-int)

(defcstruct evbuffer
	(*buffer :unsigned-char)
	(*orig_buffer :unsigned-char)
	(misalign size-t)
	(totallen size-t)
	(off size-t)
	(*cb :pointer) ; struct?
	(*cbarg :pointer))

(defcstruct event-base)

(defcstruct evhttp-request)

(defcstruct evhttp)

(defcfun ("evbuffer_new" %evbuffer-new) :pointer)

(defcfun ("evbuffer_add_printf" %evbuffer-add-printf) :void
	(buf evbuffer)
	(msg :string)
	(uri :string))

(defcfun ("evhttp_request_uri" %evhttp-request-uri) :string
	(req evhttp-request))

(defcfun ("evhttp_send_reply" %evhttp-send-reply) :void
	(req evhttp-request)
	(flag :int)
	(msg :string)
	(buf evbuffer))

;;; unwind-protect to create evbuffer-new?

(defun generic-handler (req &optional (arg nil))
	(let ((buf (%evbuffer-new)))
		(if (null buf)
			(error "Failed to create response buffer")
			(progn
				(%evbuffer-add-printf buf "Requested: %sn" (%evhttp-request-uri  
req))
				(%evhttp-send-reply req HTTP_OK "OK" buf)))))

(defcfun ("event_init" %event-init) :event-base)

(defcfun ("evhttp_start" %evhttp-start) :evhttp
	(address :char)
	(port :unsigned-short))

(defcfun ("evhttp_set_gencb" %evhttp-set-gencb) :void
	(http evhttp)
	???)

(defcfun ("event_dispatch" %event-dispatch) :int)

(defcfun ("evhttp_free" %evhttp-free) :void
	(http evhttp))

;;; MAIN SERVER START UP FUNCTION

;(server "0.0.0.0" 5009)

(defun server (host port)
	(%event-init)
	(let ((httpd %evhttp-start host port)
		(%evhttp-set-gencb httpd #'generic-handler nil)
		(%event-dispatch)
		(%evhttp-free httpd))))




More information about the cffi-devel mailing list