Who is my Community?

“Executive” Summary

This post is more of an op-ed piece than anything technically illuminating, and certainly not Haskell specific. Those not wishing to be exposed to a high level of pontification may prefer to pass. Similarly, those unused to my writing style may be disconcerted at just how many digressions I manage to fit into a short blog post. Imagine something like Steve Yegge, but without the wit, expertise or insight, and you shouldn’t be too far off. Again, please pass if this is an issue for you.

If you are a time-starved executive type who needs to cut to the content and ignore the crap, see immediately below.

tl;dr: We built something which might be of interest to others. Should we bother to make it accessible to others when it would make our own lives, and those of our existing community, harder?

wxHaskell – why bother?

I am the lead maintainer of wxHaskell, a Haskell binding for the wxWidgets library. As part of a coming push to make wxHaskell compatible with wxWidgets 2.9, we have done quite a bit of work which has raised questions as to the ‘best’ way forward in a number of areas.

As Open Source communities go, the Haskell community is probably a relative outlier in a number of ways which matter to an Open Source Haskell contributor:

  • It is relatively small;
  • Its members have an astonishingly wide range of abilities and interests;
  • It is incredibly good natured and helpful to all, pretty much regardless of level of ability.

The small size of the community means that many projects struggle to maintain a significant level of engagement over time. There are, I think, relatively few people interested in the nuts and bolts of maintaining a GUI binding, and this effort is split across several GUI bindings (Gtk2Hs and wxHaskell being probably the best supported, but with QTHaskell and HOC). There are good reasons for the split opinion on which GUI library to bind with, and I won’t explore them here.

Why not Gtk?

One aspect of wxHaskell which I hugely appreciate is that it works on the three main platforms: Linux and other unices; Windows and OS X, and delivers ‘native’ application look and feel without too much problem on all, and this is an attribute I’m determined we should keep.

In common with many programming languages, Haskell has an FFI binding which has no problem interfacing with libraries written in C, but cannot natively interface with libraries written in C++. There are very good reasons for this (basically that there is no way for anything other than the C++ compiler which originally compiled a C++ library to know how to call or link to the functions in that library – or more technically, every C++ compiler does name mangling differently).

This is probably the reason that GTK has become the default GUI binding for many non-mainstream languages. GTK may have <opinion-not-fact>a rather ugly approach to object-orientation</opinion-not-fact>, but all of its APIs are accessible in standard C, and it is therefore relatively straightforward to write a low-level GTK binding.

GTK is an outlier in the GUI world, however. Most GUI libraries are designed in object oriented fashion, using languages, like C++, which natively support object orientation. There are also good reasons for this: GUIs are <opinion-again> one of the few application areas </opinion-again> where classical object orientation is a very good way of expressing design (the other is designing libraries for classifying shapes, which seems to be a staple of OO tutorials, but not something for which I have seen an overwhelming demand in my professional life).

Wrapping C++ for beginners

Fortunately, it is very simple to make C++ code comprehensible to systems which only understand C. Suppose you have a class something like (borrowed from C++ Language Tutorial):

class CRectangle {
    int x, y;
  public:
    void set_values(int, int);
    int get_area() const;
};

It is straightforward to write a wrapper for the class, callable in C, which looks (if you ignore error checking etc.) something like:

extern "C" {
  void CRectangle_set_values(CRectangle* self, int x, int y) {
    self->set_values(x, y);
  }
  int CRectangle_get_area(CRectangle* self) {
    return self->get_area();
  }
}

You will notice that in each case, we pass around a pointer to the C++ object and use it to call the C++ function from within a function declared (with the “C” modifier) as being compatible with C calling and linker conventions.

Most of wxHaskell is wrapper code of this type. It’s not hard to write, but there is enough of it required that the writing soon becomes tedious and error prone. SWIG is designed to do this sort of thing, but it doesn’t have a Haskell backend, and when I started to work on one I quickly discovered that the documentation is a long way out of sync with SWIG itself, although the SWIG community is very helpful on the mailing lists. I may come back to a SWIG backend one day, but life is short!

That was a pretty long digression which was aimed at saying the what we have actually built is a C binding to wxWidgets. This is therefore just as accessible to most language FFIs out there as GTK, and would form a pretty good basis for a wxWidgets binding for many non-mainstream languages.

Standing on the shoulders of giants (and the not-so-giant)

Now, all of this good stuff is built on a wide range of Open Source code. Obviously the most important component is wxWidgets itself, but wxHaskell itself was forked from wxEiffel. We also use wx-config-win, a replacement for wx-config on Windows machines, and a project called wxC was forked some time back from wxEiffel (I think) to make a generic C wrapper.

In common with many Open Source projects, unfortunately many of these are moribund – the original contributors moved on and were never replaced, and so we end up with a fork or replace question. In most cases the answer to this is easy: fork – replace is almost always too costly. However Haskell is very productive indeed, which puts the question more finely in balance, and leads me (barring a few more digressions) to what I am really pondering.

How can I best serve ‘the community’ and what is that community anyway?

As I mentioned, right now we have a fairly complete C wrapper for wxWidgets. It builds as a DLL/shared library, and uses plain C headers, which means it could be used by pretty much any language.

There’s a barrier though. In order to make it as easy as possible for the Haskell community to set up and use wxHaskell, we have used a very Haskell-centric approach to building the library (Cabal, which is the standard way of distributing Haskell source libraries).

Unfortunately, I’m sure this would be a disincentive to anyone from, say, the Ocaml, Forth, Lisp or pretty much any other language community from using or contributing to the C wrapper (“waddya mean I need to download 200MB of Haskell Platform just to build a C library?”). I certainly know that I get discouraged when looking at a potentially interesting project only to discover that I need to locate 15 different packages before I even get to try to build it – an operation which is far from guaranteed to be successful with many projects.

So now I, or rather the wxHaskell community, recognise that we have a conflict of interest: we have built something which might be useful to many other groups (but we’re not sure if there is anyone out there who cares), but making life easier for those other groups will make life harder for our existing community, at least in the short term.

However, the other side of the calculation is that if other language communities get involved in contributing to the C binding, we get a larger community with a greater level of contrbution and engagement.

So we finally come to the point: is anyone out there interested in a C binding to wxWidgets, and if so, are they interested enough to want to help?

15 thoughts on “Who is my Community?”

  1. Isn’t it amazing. In the end it boils down to “give me C” 😉 I’d be interested but well I’d some work to do to earn my living. I know C quite well and to be honest I’d not even would go near C++. But aren’t we talking about wrapping C++?

  2. On a practical side, I think the best way to gauge interest in C bindings to wxWidgets is to simply wait for interested parties to join and continue with a Haskell build system in the meantime. If someone decides to jump the Haskell hoop, then he is definitely interested and worth a change in direction.

    Of course, we need to be talkative, so that the hoop jumper won’t get stuck in the hoop.

  3. The Cabal dependency isn’t so bad on Linux though, is it? Both cabal and the haskell platform are in most package management systems. And even for Windows and Mac, a single 90 or 150 MB download, respectively, isn’t that bad nowadays.

    I’m not saying you should definitely open source the C bindings, though. You can open source it and see if people are interested. If they’re not, there’s no loss to you. But if they are, this might mean more work (answering emails, fixing bugs) for you.

    1. The C binding is already open source – see http://code.haskell.org/wxhaskell/wxcore/src and look in the cpp and include directories – this will change to a separate wxc directory shortly, but the code is basically the same.

      I don’t see the Haskell dependency as a show-stopper, but I think many people think that Haskell is much harder than it really is and might be put off – although if it was *that* hard, I wouldn’t be able to do it, as I’m actually a bear of small brain 😉

  4. The wxD library (D wrapper for wxWidgets) statically linked with an older wxC wrapper based on wxWidgets v2.6.4. Your new wxC wrapper could be very useful to the project (I am not the maintainer of wxD, but currently it’s not really maintained anymore since the main contributor has said he’s leaving the project). I’ll give your new wxC a go as soon as your repo is merged into wxHashell’s mainline. Whichever build system you use is fine as long as wxC is buildable (I’m running win32 and *nix here).

    Using a DLL approach is actually a good thing (for D). Currently wxWidgets, wxC and wxD were statically linked to the executable and this would sometimes produce so many symbol names that it would break the linker on win32 systems (due to OMF format shenanigans). Plus the wxWidgets team seems to have dropped DMC support in recent versions (The C++ compiler which produces OMF-type object files which are linkable to D on win32 systems). With DLLs these problems go away.

    D is in a need of a good standards-compliant GUI library with a liberal license, so if I can get wxD to work with the new wxC I’ll be interested in helping out. Talk to you soon..

  5. So we finally come to the point: is anyone out there interested in a C binding to wxWidgets, and if so, are they interested enough to want to help?

    I’m interested and would like to know what skills would be required?

    Otoh, I believe your message would have greater impact on wx list which is, hopefully, monitored by developers of other languages?

    1. In terms of skills, the basic requirement is knowing enough C++ to be able to write a C wrapper. This is a very small subset of C++ (basically understanding what to do with reference types).

      If we ever have the resources to replace the hand-written wrappers with something auto-generated, then it will likely entail knowledge of whatever we use to generate the wrappers. XML (and therefore XSLT) is probably the front-runner, but we are a long way from such a decision.

  6. Andrej Mitrovic :
    D is in a need of a good standards-compliant GUI library with a liberal license, so if I can get wxD to work with the new wxC I’ll be interested in helping out. Talk to you soon..

    Count on my help as well. 😉

  7. I can build wx2.9 via MinGW32 on Msys and I can build & run samples. I can build wxhaskell/wxdirect, but I can’t build wxhaskell/core:

    C:\wxhaskell-dev\wxcore>cabal install
    Resolving dependencies…
    cabal: cannot configure wxcore-0.13.1. It requires wxc -any
    There is no available version of wxc that satisfies -any

    What am I missing?

    1. A couple of things. Dave’s repo currently only builds (for sure) on Linux.
      First, you need at least a patch to wx-config-win32 which sorts out library names (msys libraries are incorrectly named due to a 2.8/2.9 change)

      At line 948, you need:
      if (cfg[“BUILD”] == “debug” && cfg[“DEBUG_FLAG”] == “default”)
      po[“WXDEBUGFLAG”] = “”;

      if (cfg[“DEBUG_FLAG”] == “1”)
      po[“WXDEBUGFLAG”] = “”;

      .
      Second, in wxc/Setup.hs you need to change line 82 (just after output readProcess “wx-config” [“–libs”, “std,gl,stc,xrc,richtext,aui,media”, “–cppflags”] “”

      This is needed because wx-config-win does not support the new ‘all’ flag, and I haven’t had time to fix wx-config-win properly.

      Third, the library then builds for me, but fails to link (link errors in StyledTextCtrl). I hope to work out why tonight or tomorrow.

      I will get in touch with you directly by e-mail, so that I can pull in Dave Tapley, who is doing most of the work, and we can continue over mail – this is not the ideal medium, I think.

      1. I also realised that you are not using Dave’s development repo, which you will need to do for now. I’ll mail instructions to you on getting it (but doesn’t build on Windows yet, so you may prefer to wait or work on Linux – I should have a Windows build within a couple of days).

  8. jeremyodonoghue :
    I also realised that you are not using Dave’s development repo, which you will need to do for now. I’ll mail instructions to you on getting it (but doesn’t build on Windows yet, so you may prefer to wait or work on Linux – I should have a Windows build within a couple of days).

    I was using his new repo, but we’ll discuss this over mail. Since Windows doesn’t work right now I’ll give it a go on *nix. Thanks for your quick response.

  9. I know there’s a bit of delay here, but I’m very interested in a plain C wrapper for wxWidgets as well for a pair of projects I’m engaged in. I’d like a cross-platform native-UI that I can use, and unfortunately, I am unable to work with C++.
    My primary targets would be windows and macOS, with linux as a happy bonus.

Leave a reply to Andrej Mitrovic Cancel reply