Hi! I wanted to play arround a little with the D programming languageD[1], specially with C interfacing, so I wrote this "bindings" for libev[2].
This was written using GDC (D 1.0), using phobos and libev 2.01 on a 32 bits x86. I don't know if it works under other plataforms / combinations, but I'll be very happy to know your experiences =) For know there is only the same API as in C, but a more higher level API is planned. It took me a couple of hours to put it toguether (with testing, the struct alignment was the only "tricky" part). I'm looking for some feedback before I start with the higher level API, so comments are much appreciated. The "ev" module (ev.d) and a simple test (test.d) are attached. You can compile it with: gdc -o test -lev ev.d test.d (you need libev 2.01 installed with EV_MULTIPLICITY=1, for now at least, if you have disabled some event types, take a look at version identifiers EV_ENABLE_SELECT and EV_XXX_ENABLE). Of course, this isn't even a release yet, just a preview for comments, use it at your own risk ;) TIA [1] http://digitalmars.com/d/ [2] http://software.schmorp.de/pkg/libev.html -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- - is there a perl version of php?... cause i have cgi-bin access with perl and want to use php scripts.
/+ + D Programming Language "bindings" to libev + <http://software.schmorp.de/pkg/libev.html> + + Written by Leandro Lucarella (2008). + + Placed under BOLA license <http://auriga.wearlab.de/~alb/bola/> which is + basically public domain. + +/ module ev; enum: uint { UNDEF = 0xFFFFFFFFL, // guaranteed to be invalid NONE = 0x00L, // no events READ = 0x01L, // ev_io detected read will not block WRITE = 0x02L, // ev_io detected write will not block IOFDSET = 0x80L, // internal use only TIMEOUT = 0x00000100L, // timer timed out PERIODIC = 0x00000200L, // periodic timer timed out SIGNAL = 0x00000400L, // signal was received CHILD = 0x00000800L, // child/pid had status change STAT = 0x00001000L, // stat data changed IDLE = 0x00002000L, // event loop is idling PREPARE = 0x00004000L, // event loop about to poll CHECK = 0x00008000L, // event loop finished poll EMBED = 0x00010000L, // embedded event loop needs sweep FORK = 0x00020000L, // event loop resumed in child ERROR = 0x80000000L, // sent when an error occurs } enum: uint { // bits for ev_default_loop and ev_loop_new // the default AUTO = 0x00000000UL, // not quite a mask // flag bits NOENV = 0x01000000UL, // do NOT consult environment FORKCHECK = 0x02000000UL, // check for a fork in each iteration // method bits to be ored together SELECT = 0x00000001UL, // about anywhere POLL = 0x00000002UL, // !win EPOLL = 0x00000004UL, // linux KQUEUE = 0x00000008UL, // bsd DEVPOLL = 0x00000010UL, // solaris 8 / NYI PORT = 0x00000020UL, // solaris 10 } enum { NONBLOCK = 1, // do not block/wait ONESHOT = 2, // block *once* only } enum how { CANCEL = 0, // undo unloop ONE = 1, // unloop once ALL = 2, // unloop all loops } extern (C) { version (EV_ENABLE_SELECT) { } else { version = EV_PERIODIC_ENABLE; version = EV_STAT_ENABLE; version = EV_IDLE_ENABLE; version = EV_FORK_ENABLE; version = EV_EMBED_ENABLE; } alias double ev_tstamp; struct ev_loop_t; template EV_COMMON() { void* data; } template EV_CB_DECLARE(TYPE) { void function (ev_loop_t*, TYPE*, int) cb; } template EV_WATCHER(TYPE) { int active; // private int pending; // private int priority; // private mixin EV_COMMON; // rw mixin EV_CB_DECLARE!(TYPE); // private } template EV_WATCHER_LIST(TYPE) { mixin EV_WATCHER!(TYPE); ev_watcher_list* next; // private } template EV_WATCHER_TIME(TYPE) { mixin EV_WATCHER!(TYPE); ev_tstamp at; // private } align (4) { struct ev_watcher { mixin EV_WATCHER!(ev_watcher); } struct ev_watcher_list { mixin EV_WATCHER_LIST!(ev_watcher_list); } struct ev_watcher_time { mixin EV_WATCHER_TIME!(ev_watcher_time); } struct ev_io { mixin EV_WATCHER_LIST!(ev_io); int fd; // ro int events; // ro } struct ev_timer { mixin EV_WATCHER_TIME!(ev_timer); ev_tstamp repeat; // rw } version (EV_PERIODIC_ENABLE) { struct ev_periodic { mixin EV_WATCHER_TIME!(ev_periodic); ev_tstamp offset; // rw ev_tstamp interval; // rw ev_tstamp function(ev_periodic *w, ev_tstamp now) reschedule_cb; // rw } } struct ev_signal { mixin EV_WATCHER_LIST!(ev_signal); int signum; // ro } struct ev_child { mixin EV_WATCHER_LIST!(ev_child); int pid; // ro int rpid; // rw, holds the received pid int rstatus; // rw, holds the exit status, use the // macros from sys/wait.h } version (EV_STAT_ENABLE) { version (Windows) // alias _stati64 ev_statdata; { pragma (msg, "ev_stat not supported in windows " "because I don't know the " "layout of _stati64"); static assert(0); // Maybe this should work? //static import stat = std.c.windows.stat; //alias stat.struct_stat ev_statdata; } else // It should be POSIX { static import stat = std.c.unix.unix; alias stat.struct_stat ev_statdata; } struct ev_stat { mixin EV_WATCHER_LIST!(ev_stat); ev_timer timer; // private ev_tstamp interval; // ro const char *path; // ro ev_statdata prev; // ro ev_statdata attr; // ro int wd; // wd for inotify, fd for kqueue } } version (EV_IDLE_ENABLE) { struct ev_idle { mixin EV_WATCHER!(ev_idle); } } struct ev_prepare { mixin EV_WATCHER!(ev_prepare); } struct ev_check { mixin EV_WATCHER!(ev_check); } version (EV_FORK_ENABLE) { struct ev_fork { mixin EV_WATCHER!(ev_fork); } } version (EV_EMBED_ENABLE) { struct ev_embed { mixin EV_WATCHER!(ev_embed); ev_loop_t* other; // ro ev_io io; // private ev_prepare prepare; // private ev_check check; // unused ev_timer timer; // unused ev_periodic periodic; // unused ev_idle idle; // unused ev_fork fork; // unused } } } int ev_version_major(); int ev_version_minor(); uint ev_supported_backends(); uint ev_recommended_backends(); uint ev_embeddable_backends(); ev_tstamp ev_time(); void ev_sleep(ev_tstamp delay); // sleep for a while // Sets the allocation function to use, works like realloc. // It is used to allocate and free memory. // If it returns zero when memory needs to be allocated, the library // might abort // or take some potentially destructive action. // The default is your system realloc function. void ev_set_allocator(void* function(void* ptr, int size)); // set the callback function to call on a // retryable syscall error // (such as failed select, poll, epoll_wait) void ev_set_syserr_cb(void* function(char* msg)); extern ev_loop_t* ev_default_loop_ptr; ev_loop_t* ev_default_loop_init(uint flags); // create and destroy alternative loops that don't handle signals ev_loop_t* ev_loop_new(uint flags); void ev_loop_destroy(ev_loop_t*); void ev_loop_fork(ev_loop_t*); ev_tstamp ev_now(ev_loop_t*); void ev_default_destroy(); void ev_default_fork(); uint ev_backend(ev_loop_t*); uint ev_loop_count(ev_loop_t*); void ev_loop(ev_loop_t*, int flags); void ev_unloop(ev_loop_t*, how); void ev_set_io_collect_interval(ev_loop_t*, ev_tstamp interval); void ev_set_timeout_collect_interval(ev_loop_t*, ev_tstamp interval); void ev_ref(ev_loop_t*); void ev_unref(ev_loop_t*); void ev_once(ev_loop_t*, int fd, int events, ev_tstamp timeout, void function(int revents, void* arg), void* arg); void ev_feed_event(ev_loop_t*, void *w, int revents); void ev_feed_fd_event(ev_loop_t*, int fd, int revents); void ev_feed_signal_event (ev_loop_t*, int signum); void ev_invoke(ev_loop_t*, void *w, int revents); int ev_clear_pending(ev_loop_t*, void *w); void ev_io_start(ev_loop_t*, ev_io *w); void ev_io_stop(ev_loop_t*, ev_io *w); void ev_timer_start(ev_loop_t*, ev_timer *w); void ev_timer_stop(ev_loop_t*, ev_timer *w); void ev_timer_again(ev_loop_t*, ev_timer *w); version (EV_PERIODIC_ENABLE) { void ev_periodic_start(ev_loop_t*, ev_periodic *w); void ev_periodic_stop(ev_loop_t*, ev_periodic *w); void ev_periodic_again(ev_loop_t*, ev_periodic *w); } void ev_signal_start(ev_loop_t*, ev_signal *w); void ev_signal_stop(ev_loop_t*, ev_signal *w); /* only supported in the default loop */ void ev_child_start(ev_loop_t*, ev_child *w); void ev_child_stop(ev_loop_t*, ev_child *w); version (EV_STAT_ENABLE) { void ev_stat_start(ev_loop_t*, ev_stat *w); void ev_stat_stop(ev_loop_t*, ev_stat *w); void ev_stat_stat(ev_loop_t*, ev_stat *w); } version (EV_IDLE_ENABLE) { void ev_idle_start(ev_loop_t*, ev_idle *w); void ev_idle_stop(ev_loop_t*, ev_idle *w); } void ev_prepare_start(ev_loop_t*, ev_prepare *w); void ev_prepare_stop(ev_loop_t*, ev_prepare *w); void ev_check_start(ev_loop_t*, ev_check *w); void ev_check_stop(ev_loop_t*, ev_check *w); version (EV_FORK_ENABLE) { void ev_fork_start(ev_loop_t*, ev_fork *w); void ev_fork_stop(ev_loop_t*, ev_fork *w); } version (EV_EMBED_ENABLE) { // only supported when loop to be embedded is in fact embeddable void ev_embed_start(ev_loop_t*, ev_embed *w); void ev_embed_stop(ev_loop_t*, ev_embed *w); void ev_embed_sweep(ev_loop_t*, ev_embed *w); } bool ev_is_pending(TYPE)(TYPE* w) { return w.pending; } bool ev_is_active(TYPE)(TYPE* w) { return w.active; } int ev_priority(TYPE)(TYPE* w) { return w.priority; } void function(ev_loop_t*, TYPE*, int) ev_cb(TYPE)(TYPE* w) { return w.cb; } void ev_set_priority(TYPE)(TYPE* w, int pri) { w.priority = pri; } void ev_set_cb(TYPE)(TYPE* w, void function(ev_loop_t*, TYPE*, int) cb) { w.cb = cb; } void ev_init(TYPE)(TYPE* w, void function(ev_loop_t*, TYPE*, int) cb) { w.active = 0; w.pending = 0; w.priority = 0; ev_set_cb(w, cb); } void ev_io_set(ev_io* w, int fd, int events) { w.fd = fd; w.events = events | IOFDSET; } void ev_timer_set(ev_timer* w, ev_tstamp after, ev_tstamp repeat) { w.at = after; w.repeat = repeat; } void ev_periodic_set(ev_periodic* w, ev_tstamp ofs, ev_tstamp ival, ev_tstamp function(ev_periodic *w, ev_tstamp now) res) { w.offset = ofs; w.interval = ival; w.reschedule_cb = res; } void ev_signal_set(ev_signal* w, int signum) { w.signum = signum; } void ev_child_set(ev_child* w, int pid) { w.pid = pid; } void ev_stat_set(ev_stat* w, char* path, ev_tstamp interval) { w.path = path; w.interval = interval; w.wd = -2; } void ev_idle_set(ev_idle* w) { } void ev_prepare_set(ev_prepare* w) { } void ev_check_set(ev_check* w) { } void ev_embed_set(ev_embed* w, ev_loop_t* other) { w.other = other; } void ev_fork_set(ev_fork* w) { } void ev_io_init(ev_io* w, void function(ev_loop_t*, ev_io*, int) cb, int fd, int events) { ev_init(w, cb); ev_io_set(w, fd, events); } void ev_timer_init(ev_timer* w, void function(ev_loop_t*, ev_timer*, int) cb, ev_tstamp after, ev_tstamp repeat) { ev_init(w, cb); ev_timer_set(w, after, repeat); } void ev_periodic_init(ev_periodic* w, void function(ev_loop_t*, ev_periodic*, int) cb, ev_tstamp ofs, ev_tstamp ival, ev_tstamp function(ev_periodic *w, ev_tstamp now) res) { ev_init(w, cb); ev_periodic_set(w, ofs, ival, res); } void ev_signal_init(ev_signal* w, void function(ev_loop_t*, ev_signal*, int) cb, int signum) { ev_init(w, cb); ev_signal_set(w, signum); } void ev_child_init(ev_child* w, void function(ev_loop_t*, ev_child*, int) cb, int pid) { ev_init(w, cb); ev_child_set(w, pid); } void ev_stat_init(ev_stat* w, void function(ev_loop_t*, ev_stat*, int) cb, char* path, ev_tstamp interval) { ev_init(w, cb); ev_stat_set(w, path, interval); } void ev_idle_init(ev_idle* w, void function(ev_loop_t*, ev_idle*, int) cb) { ev_init(w, cb); ev_idle_set(w); } void ev_prepare_init(ev_prepare* w, void function(ev_loop_t*, ev_prepare*, int) cb) { ev_init(w, cb); ev_prepare_set(w); } void ev_check_init(ev_check* w, void function(ev_loop_t*, ev_check*, int) cb) { ev_init(w, cb); ev_check_set(w); } void ev_embed_init(ev_embed* w, void function(ev_loop_t*, ev_embed*, int) cb, ev_loop_t* other) { ev_init(w, cb); ev_embed_set(w, other); } void ev_fork_init(ev_fork* w, void function(ev_loop_t*, ev_fork*, int) cb) { ev_init(w, cb); ev_fork_set(w); } ev_loop_t* ev_default_loop(uint flags = AUTO) { if (!ev_default_loop_ptr) ev_default_loop_init(flags); return ev_default_loop_ptr; } }
/+ + D Programming Language "bindings" to libev + <http://software.schmorp.de/pkg/libev.html> test program. + + Written by Leandro Lucarella (2008). + + Placed under BOLA license <http://auriga.wearlab.de/~alb/bola/> which is + basically public domain. + +/ import io = std.stdio; import ev; extern (C) { static void stdin_cb (ev_loop_t* loop, ev_io *w, int revents) { io.writefln("stdin ready"); char[] ln = io.readln(); io.writef("read %d bytes: %s", ln.length, ln); ev_io_stop(loop, w); // just a syntax example ev_unloop(loop, how.ALL); // leave all loop calls } static void timeout_cb(ev_loop_t* loop, ev_timer *w, int revents) { io.writefln("timeout"); ev_unloop(loop, how.ONE); // leave one loop call } } void main() { ev_io stdin_watcher; ev_timer timeout_watcher; ev_loop_t* loop = ev_default_loop(); /* initialise an io watcher, then start it */ ev_io_init(&stdin_watcher, &stdin_cb, /*STDIN_FILENO*/ 0, READ); ev_io_start(loop, &stdin_watcher); /* simple non-repeating 5.5 second timeout */ ev_timer_init(&timeout_watcher, &timeout_cb, 1.5, 0.0); ev_timer_start(loop, &timeout_watcher); /* loop till timeout or data ready */ ev_loop(loop, 0); }
_______________________________________________ libev mailing list [email protected] http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
