Returning to C++

15 March 2014
A few weeks ago I pulled up a project I started during my early days in New Zealand but never got round to competing: knocking together some code that pulled H.264 video frames off a Logitech C920 web-cam. I finally got round to finishing the V4L2 bit that pulled the frames out, and for reasons of simplicity my plan was to throw these out on a UDP port for a Python script to capture and process, and I would work out Logitech's idiosyncrasies from that point onwards. However I had forgotten how laborious doing socket operations in C was. In the end I hacked together something that got the task done, but then took a side-step.

In the past I got round C being a bit verbose for network programming by writing a wrapper library for common operations, but I had lost track of where it had got to. Even if I found a copy, I doubt it would have included various tricks I discovered while working at my last company. In any case rewriting the wrappers in C++ has been on my to-do list for some time, and although I had pretty much written C++ off as a language worth learning, decided I ought to finally satisfy this itch.

Particulars of socket programming

A major issue with network programming is that it is all about socket handles and blocks of bytes, and these more often than not don't fall within neat class boundaries. Making wrappers for a select() based process loop feels like a padding-out not usually seen outside of government departments, so at times it is a conflict between maintaining the tight efficiency that is the culture of C programs, and actually doing a decent job of moving over to ‘proper’ C++. In hindsight a socket library was probably a poor choice.

C++ quirks

Rather than talk in-depth, I find it better to give some brief comments on things that seems to really stick out at me in the process of using C++. More often than not these are things that seem unusual rather than annoying.
C# style Accessors
When I first came across these I found them an irritation, but pretty much ever since have regarded them as a good thing to have. In C accessing structures directly from non-structure functions did not bother me because my goal was maximum efficiency, but with C++ I would want to keep internal pointers private. Writing getter functions just felt unnatural after using both C# and Python, which allow such a function to be disguised as a variable.
Constructors cannot return fail values
With C-based ADTs the “creation” function would normally return a pointer to structure which allowed the return of NULL as a generic failure indication, but with C++ constructors the only way to indicate failure is to throw an exception. Problem is that most network errors such as name resolution failures are common enough that I think exceptions are inappropriate, and hence creators are largely useless for my modus-operandi.
Non-dynamically allocated classes
The idea is that structures (especially small ones) ought to be passed by value, but keeping these on the stack as auto variables brings some subtle differences compared to how things are done with Java and dynamically allocated class instances. Copy constructors is a topic in itself that no other language I use has, which brings some counter-intuitive quirks for those used to using the ‘new’ operator.
Class scope domination
I am of the school of thought that thinks that class variables should always be explicitly referenced as such, as doing so blows away a tonne of issues related to scoping. The C++ convention of writing stuff like void Foo::bar(int value) { m_value = value; } using Hungarian Notation prefixes to separate class and local variables grates my nerves. This is particularly irritating when writing C++ wrapper around C functions, as stuff like Socket::listen() { listen(this->fdSocket,1); } causes initially odd-looking errors.
Templates
When I looked at C++ four years ago I noted how templates seemed to be influenced by Haskell's type classes, which cross-correlated with a paper I read around the same time comparing the two. Given that my Haskell is encrusted with rust I am not in a position to re-evaluate this comparison, but I am in two minds whether they add value overall to C++ or simply bloat the language. They allow content-agnostic container classes such as Vector which are very useful. But at least with gcc errors involving templates can result in error messages that are very difficult to decipher.
Namespaces
I had previously thought that Namespaces were somewhat redundant, as use of classes & sub-classes already got around the problem of global namespace pollution that is one of C's major pit-falls. I am still to be convinced otherwise.
With C++ there feels a conflict between the raw-speed C heritage, and the need for abstraction due to C++ being an object-orientated language. In the past this has made me conclude that it is better to opt for a cleaner language such as Java or Python, but those languages are clearly not suited to the type of real-time programming I have done in most of the last few years.

Unit testing

As part of the exercise, I took the opportunity to try out some C++ unit testing frameworks. Originally I had might sights on CppUnit, but eventually opted for the aptly-named GoogleTest and GoogleMock. The latter two are self-contained, but they were clearly designed to go together. While particulars of C++ mean that some syntactic trickery is needed compared to NUnit-like testing frameworks on other platforms, but once you've got over this higher-than-usual hurdle, you can get a lot done relatively quickly.

What now?

My original goal of implementing a C++ sockets library is itself complete(ish), and it naturally leads onto the temptation to use it in a project, but I know going down that road will end up with me writing some sort of media streaming server. One possibility would be porting the V4L2 bootstrap to RaspberryPi and then writing an RTSP/RTP server so that I had a home-brew network CCTV camera, but having done similar stuff at my previous company I know that would be a big undertaking. I feel less aversion to C++ compared to last time I revisited it, but for now C# has got my attention. For now..