On 20/02/18 19:50, Marc Lehmann wrote:
On Tue, Feb 20, 2018 at 10:35:01AM +0800, Andy Green <a...@warmcat.com> 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

You brought this subject up.

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 (...);

    void
    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;
    #endif

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.

That is the first constructive suggestion, thanks. It adds another layer of indirection. But actually that is probably a good idea. Reducing the scope of the includes if it is possible is also a good way.

There are other event-lib api types that are exposed in event-lib specific lws apis, eg, pass in an external loop object as the active event loop. If these are all pointers then it can be solved with forward references.

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.

Note the word "compose" has a specific meaning here...

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.

All of these event loop things are contributed. I don't think any of these extreme tricks to workaround your header clash problem will help with maintainability or source code clarity. They are just not needed to be considered with, eg, libuv.

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...

Wow!  You are living down to my expectations :-)

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...

No... you preferred to attack the user and find a way that nothing needed to change on your side, even when a comparable, more popular library has no problem with its header hygiene doing the same thing.

As I said I will just leave it unselectable for choose-at-runtime in cmake - and suggest people avoid using libev.

-Andy

_______________________________________________
libev mailing list
libev@lists.schmorp.de
http://lists.schmorp.de/mailman/listinfo/libev

Reply via email to