libev and libevent

Marc Lehmann schmorp at
Tue Feb 20 12:50:24 CET 2018

On Tue, Feb 20, 2018 at 10:35:01AM +0800, Andy Green <andy at> wrote:
> > Not really, even C supports opaque types.
> No, there is no "not really" about it.
> C supports opaque type pointers because the size of a pointer is known
> regardless of the details of what it points to.

To be pedantic, C supports opaque pointers because it is defined to do so,
not because pointers naturally all have the same size (they don't).

Anyhow, I don't think this is the right place for introductory programming
in C, but the solution, as already mentioned, is to move libev code into
e.g. lws-libev.c, libevent code into lws-libevent.c and so on, and then
define an abstraction to those, e.g.

   struct lws_ev_watcher;

   lws_ev_io_watcher *
   lws_ev_io_new (...);

   lws_ev_io_start (lws_ev_watcher *, ...);


lws_ev_watcher is your opaque data type, and lws_ev_new etc. are the
methods used to access them.

Then you can use those in your lws_io_watcher struct:

   struct lws_io_watcher {
   #ifdef LWS_WITH_LIBEV
           lws_ev_io_watcher *ev_watcher;

Quite possibly, lws_ev_io_watcher could even be identical to
struct ev_io, and with some work, it doesn't even have to be a pointer, and
lws_ev_watcher might not need to be a separate data type either.

Since you are not really telling us why you think you need this, it's hard to
tell you which solution might be best.

> However you cannot compose an opaque / forward-referenced struct into
> another struct with type safety, because the size of the undefined thing is
> unknown.

Yes, you can, multiple ways.

> I must have your struct definition and that means I must have your headers.

Yes, but not in the same source file as the headers for libevent. This is a
pretty standard problem with pretty standard solutions.

You can do away with pointers with some tricks, as the libev ABI has a
fixed watcher size that you could determine at compile time and reserve
enough space in your lws_io_watcher struct. This would result in virtually
no performance loss due to the indirection.

It's not trivial, but certainly possible with commonly used programming
techniques. It probbaly wouldn't buy you anything that you couldn't beat
by embedding libev, though.

The other problem, the ABI clash, can either be fixed with a custom libev
version not compiling in the event code (easy to do), or by using e.g.
shared libraries and dlopen, which allows you to open both libevent and
libev despite symbol clashes.

Again, not trivial, but what you are trying to do is hardly typical.

Embedding libev, would enable a lot of other possible solutions as well.

A last comment on your style here - I have looked hard, but I still
couldn't find a good explanation (or any explanation) of why you need to
do it this way as opposed to separate builds or even backends for each
event library, which might be faster, more efficient, and easier to extend
than your current approach (compare e.g. how gtk+ selects backends, how
opengl/opencl work and so on).

Nothing you said explains why you need to be able to switch event
libraries at runtime, as opposed to e.g. select it at runtime by loading
the correct backend library.

To say it bluntly, you come about as very tight-lipped about your needs
and a bit arrogant, when considering that your programming skills are
comparatively limited, given you are quite troubled by even simple
abstraction problems in C...

Both Harald and I have tried to help you, and it would suit you well if you
would explain your problem a bit more and would use rational arguments
instead of shouting at people...

                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_    
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      schmorp at
      -=====/_/_//_/\_,_/ /_/\_\

More information about the libev mailing list