C++ Serialization

I am looking for a C++ serialization library/framework with these features:
1. Binary: Space efficient binary format.
2. Programming language independent: Should have an implementation in most common popular programming languages.
3. Portable across platforms: Should be able to write a file on a FreeBSD web server and be able to read that same file on an Android device.
4. Open format: The format of the generated files should be well documented.
5. Clearly declared file structure: There should be a way to put down the file structure in one place and track changes to it.
6. Non-intrusive: Users of the library must not be required to make changes to existing data-structures that they want to serialize/deserialize. For example, I should not be required to derive my class from a “Serializable” class.
7. Large files: Should work fine for files several GB in size.

With the current state of the art, this is what is on offer:

Feature protobuf boost::serialization MFC
Binary Y Y Y
Programming Language Independent Y ? N
Portable across platforms Y N N
Open Format Y ? ?
Clearly declared file structure Y N N
Non-intrusive Y Y N
Large files N Y Y
Old version of code can read files created by newer versions Y N ?

cadview – 2: Running on Windows

Here are two examples of cadview clients running on Windows. The first is simply the earlier gladeui sample built on Windows using MSVC. Headers and libraries for GTK+ (http://www.gtk.org/download/win32.php) need to be installed. A VC++ project [1] was created to refer to the gladeui source files. The project is located at /src/msvc/gladeui. No significant changes were made to the gladeui source.

The second example is called winui and talks directly to the Windows API and GDI+. When handling paint events we require an object using which to perform graphics output. In the GTK+ case, I could simply create the cairo_t object within the handler. In case of the Windows API, the output must be performed via an HDC which is passed as a parameter with the WM_PAINT event. In order to accommodate this, cad_gui_view::paint was modified to take a cad_gui_view::graphics_type& as a parameter. winui is located at /src/msvc/winui in the repo.


  1. ^ I had to fall back on a handcrafted MSVC build since CMake failed to find GTK+ and Boost on Windows. The MSVC solution can be found at /src/msvc/msvc.sln within the repository. boost::regex (http://www.boostpro.com/download/) headers and libraries need to be installed for both examples.

Linux Package Names

Package Name on Repo
GNU Standard C++ Library libstdc++
Documentation for the GNU standard C++ library libstdc++-docs
The Boost C++ headers and shared development libraries boost-devel
HTML documentation for the Boost C++ libraries boost-doc
Apache HTTP Server httpd
The MySQL server and related files mysql-server
PHP scripting language for creating dynamic web sites php
A module for PHP applications that use MySQL databases php-mysql
Free Feature-rich PHP Mailer php-swift-Swift
Development files for GTK+ gtk2-devel
The Boost C++ headers and shared development libraries boost-devel
C++ support for GCC gcc-c++

cadview – 1: Introduction

cadview is a C++ library which provides a cross-platform GUI widget for 2D drafting. Presently, the following features are supported:

  • Zoom/Pan
  • Polyline tool
  • Entering x,y co-ordinates via mouse selection or text entry

Installation

No installation packages are available yet and the executable has to be built from source. cadview depends on the following tools and libraries:

On a Fedora 16/17 machine, you can install the above dependencies as follows:

Obtain the source using Mercurial as follows:

This should place the source in a directory named cadview in your current directory. To build the binaries:

gladeui is a test application that uses cadview on GTK+. You can run gladeui as follows:

Select File>Polyline to activate the polyline tool. The UI controls are as follows:

  • Click to add a point to the polyline
  • A point can also be added by entering an x,y co-ordinate pair in the textbox and hitting <Enter>
  • Pan by holding down the middle mouse button
  • Zoom by turning the mouse wheel
  • Right-click or hit <Esc> to end the polyline

Screenshot of cadview

Design Overview

The visible area of the widget – the view – is represented by the cad_gui_view class. cad_gui_view does not interact directly with the underlying GUI but instead depends on a pair of adaptor classes for GUI facilities.

The first adaptor class is the template parameter U of cad_gui_view and provides facilities like getting the position of the mouse cursor (get_mouse_position) and invalidating the view (invalidate). The second adaptor class is the U::graphics_type type. This type provides facilities to draw on screen (draw_polyline, move_to, line_to) and converting between screen and world co-ordinates (device_to_user).

The cad_gtk_adaptor is an implementation of the first adaptor class (the U parameter) using GTK+. cad_cairo_graphics implements the U::graphics_type using cairo. In a similar way, we can create adaptors for other GUI platforms (e.g. cad_windows_adaptor to wrap around Windows API and cad_windows_graphics to talk to an HDC).

MySQL calls via PDO fail silently

By default any error that occurs on a MySQL call via PDO fails quietly. The caller must inspect $pdo->errorCode() to see if the call succeeded/failed. This behaviour can be changed by setting the ATTR_ERRMODE attribute either while constructing the PDO object or after construction via setAttribute.

Test if a Point lies inside a Polygon (from CGA FAQ)

The CGA FAQ describes an algorithm to test if a point lies within a polygon. Roughly speaking, you start from the point and travel north. If you cross an odd number of sides, it means that you were within the polygon when you started and vice versa.

Test if a point lies inside or outside a polygon

The details of the solution can be found in the CGA FAQ linked above. A C++ implementation can be found here: http://code.google.com/p/curve-project/source/browse/trunk/lab/cgafaq/cgafaq.h The function cgafaq::point_in_polygon takes a point and a polygon and returns whether or not the point lies inside the polygon. This is a direct translation of the code from the FAQ.

Disclaimer: This post and the code provided are not endorsed by any of the contributors to the CGA FAQ.

Orientation of Polygons (from CGA FAQ)

The orientation of a polygon tells us if the vertices are ordered clockwise or counter-clockwise as we move along the perimeter. This is determined by calculating the polygon’s signed area which is positive for counter-clockwise orientation and negative for clockwise orientation. A quicker algorithm is to determine the signed area of the triangle formed by the lowest right most vertex and it’s immediate neighbors.

The details of the solution can be found in the CGA FAQ linked above. A C++ implementation can be found here: http://code.google.com/p/curve-project/source/browse/trunk/lab/cgafaq/cgafaq.h The function cgafaq::orientation has two overloads. The first computes orientation for three vertices and the second calculates the orientation of a polygon.

Disclaimer: This post and the code provided are not endorsed by any of the contributors to the CGA FAQ.

Distance of a Point from a Line (from CGA FAQ)

The distance of a point from a line is the length of a perpendicular drawn from the point to the line. Here are the possibilities:

  • Perpendicular meets on the line segment
  • Perpendicular meets on a forward/backward extension of the line segment

Distance of a point from a line

The details of the solution can be found in the CGA FAQ linked above. A C++ implementation can be found here: http://code.google.com/p/curve-project/source/browse/trunk/lab/cgafaq/cgafaq.h The function cgafaq::distance_from_line takes the start and end points of the line and the point from which distance is to be calculated. r and s are output parameters calculated as described in the FAQ.

Note that if distance is not important and only a perpendicular needs to be generated then there is a simpler way to construct one.

Disclaimer: This post and the code provided are not endorsed by any of the contributors to the CGA FAQ.

Intersection of Line Segments (from CGA FAQ)


Intersection of two line segments
involves the following cases:

  • Segments are parallel
  • Segments are collinear/coincident
  • One segment intersects the extension of the other
  • Extension of one segment intersects the extension of the other
  • Segments intersect each other.

Intersection of Two Line Segments

The details of the solution can be found in the CGA FAQ linked above. A C++ implementation can be found here: http://code.google.com/p/curve-project/source/browse/trunk/lab/cgafaq/cgafaq.h The function cgafaq::intersect takes 4 points — the start and end points of each of the lines. r and s are output parameters calculated as described in the FAQ.

Disclaimer: This post and the code provided are not endorsed by any of the contributors to the CGA FAQ.

C++ Windows GUI Wrapper

App0 is a C++ wrapper over Windows API calls for a typical windowed application. This is similar to the framework used in curve. The design is mostly drawn from Win32 Programming by James M. Newcomer and Brent Rector.

The BaseWnd class wraps around a HWND. CreateWindowEx is called in the constructor. Before the CreateWindowEx call, I register the window class if it has not already been registered.

Since the WindowProc cannot be a member function, I use two non-members: InitWndProc is used till a WM_CREATE is received and BaseWndProc is used for the rest of the windows lifetime.

InitWndProc forwards all messages except WM_CREATE to DefWindowProc. WM_CREATE is forwarded to BaseWnd_OnCreate which saves the object pointer (passed to CreateWindowEx) at GWL_USERDATA and also replaces the window procedure (currently InitWndProc) with BaseWndProc.

BaseWndProc forwards all messages to the static BaseWnd::WndProc method which retrieves the object pointer and forwards messages to the BaseWnd::WndProc instance method. The instance method behaves like a typical WindowProc and forwards selected messages to other instance methods (OnWmClose, OnWmDestroy) while relegating all other messages to DefWindowProc.

Call stack for message handler
Call stack for message handler

I use InitWndProc initially because until WM_CREATE the object pointer has not yet been attached to the HWND and BaseWndProc depends on the object pointer.

Download source here.