Visual Studio “14″ CTP ships with a refactored C Runtime. The first thing you’ll notice is that msvcrXX.dll has been replaced by three new DLLs: appcrtXX.dll, desktopcrtXX.dll and vcruntimeXX.ddl (where XX stands for the version number so in this version it’s appcrt140.dll, desktopcrt140.dll and vcruntime140.dll).

crtdlls
You can see in this image that both desktopcrt140.dll and vcruntime140.dll depend on appcrt140.dll.

These three new DLLs export run-time routines in different categories, with some of them overlapping, as shown by the bellow table (assembled by directly analyzing the exports of the three modules).


Function

Appcrt140.dll

Desktopcrt140.dll

Vcruntime140.dll
Buffer Manipulation
Byte Classification
Character Classification
Console and Port I/O
Data Alignment
Data Conversion
Debug Routines
Directory Control
Error Handling
Exception Handling
File Handling
Floating-Point Support
Low-Level I/O
Process and Environment Control
Robustness
Searching and Sorting
Stream I/O
String Manipulation
System Calls
Time Management

Breaking CRT routines in several DLLs is not the only change. The CRT has been rewritten for safety and const correctness. Many of the routines have been re-written in C++. Here is a random example: the _open function, that was available in open.c was implemented like this in Visual Studio 2013:

In Visual Studio “14″ CTP it is available in function appcrt\open.cpp and looks like this:

UPDATE

To read more about the refactoring see the VC++ team’s blog posts:

, , , , Hits for this post: 1917 .

Visual Studio 2012 introduced a new framework for writing debugger visualizers for C++ types that replaced the old autoexp.dat file. The new framework offers xml syntax, better diagnostics, versioning and multiple file support.

Visualizers are defined in XML files with extension .natvis. These visualizers are loaded each time the debugger starts. That means if you make a change to visualizers, it is not necessary to re-start Visual Studio, just re-start the debugger (for instance detach and re-attach the debugger to the process you debug).

These files can be located under one of these locations:

  • %VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers (requires admin access)
  • %USERPROFILE%\My Documents\Visual Studio 2012\Visualizers\
  • VS extension folders

In Visual Studio “14″ CTP (in response to a UserVoice request) these files can also be added to a Visual C++ project for easier management and source control integration. All you have to do is add the .natvis file to your .vcxproj file.

Here is an example. Suppose we have the following code:

If you run this in debugger you can inspect the value of p and it looks like this:
natvis1

To change the way the point objects are visualized create a file called point.natvis with the following content:

Add this file to the project.
natvis3
When you run the application in debugger again the point object is visualized according to the per-project .natvis file.
natvis2

UPDATE
There are two things to note:

  • changes in the natvis files are now picked up automatically by the debugger; you no longer need to stop the debugging session and then start again if you make changes to a natvis file
  • natvis files from the project are evaluated after all the other files from the other possible locations; that means you can override existing (general) visualizers with project-specific visualizers

For more see Project Support for Natvis.

, , , , , Hits for this post: 1861 .

Visual Studio 2012 provides support for new features, such as code review and feedback through the use of the Work Item tracking system in TFS. (You can read more about it in this article New Code Review feature in Visual Studio 2012).

However, to be able to use these features you must use a process template that supports them. If you try to access these features without upgrading the process template you get errors.

This feature can’t be used until your Team Foundation administrator has enabled it on the team project.

To use My Work to multi-task and manage your changes, you must enable the feature on the server.
Click here to enable the new features

features1
features2

The error in the verification step for configuring the team project happen because an old process template is in use.

If your current process template is MSF for Agile Software Development version 4.x then you need to follow the steps in this article: Update a Team Project Based on an MSF v4.2 Process Template.

To being able to update, you first have to download the latest version of the process template. You can do this from Visual Studio. Go to Team > Team Project Collection Settings > Process Template Manager and download the template.
updatetemplate2

After you have the process template files go ahead and update according to the steps defined in the before mentioned article. However, there is a missing command in the first step of the process. You need to change an additional system field than those mentioned in the article:

If you need to do this for multiple projects then you’ll have to run most of these steps for each project. So here are two batch files with commands you need to run:

  • update the Team Project collection (run only once):

    Note: Make sure you set the correct URL to your collection and replace TemplateDir with the actual path of the process template that you downloaded.

  • Update the Team Project (run once for each project)

    You execute the batch passing the name of the project (in quotes if it contains spaces).

After these commands have executed successfully you can go ahead and use the new features.
updatetemplate3

, , , , , Hits for this post: 4352 .

My first Windows Store app (for Window 8.1) is now available in Windows Store. It’s called Your Chemical Name and shows names (and text) using chemical elements symbols in the Breaking Bad style.

yourchemicalname11

The application allows to:

  • customize the appearance of text, colors, background
  • customize the position of the text on the background
  • save image to a file
  • post image on a facebook album
  • share image with other apps

yourchemicalname12

yourchemicalname13

yourchemicalname14

You save the images to disk or share them on facebook or with apps supporting the Windows Share Charm.

yourchemicalname15

Here are a few screenshots:
yourchemicalname2

yourchemicalname3

yourchemicalname5

More about the application here.

Download Your Chemical Name from Windows Store.

, , , , , , , Hits for this post: 6201 .

Windows 8 features a Settings charm to display both application (the top part) and system (the bottom part) settings (you get it from swiping from the side of the screen). The system provides two entry points, Permissions and Rate and Review, the later only for applications installed through the store.

You can customize the settings charm by adding new entry points. For instance, you may want to add an About pane. If your application uses network capabilities then you have to add a privacy policy, otherwise your application will not pass the Windows Store Certification.

charms settingscharm6

In this post I will show how you can add new entries to the settings charm for Windows 8.1 applications (this won’t work for Windows 8 applications). We have to use two classes:

  • SettingsPane: enables the app to control the Settings Charm pane. The app can add or remove commands, receive a notification when the user opens the pane, or open the pane programmatically.
  • SettingsFlyout: represents a control that provides in-context access to settings that affect the current app. This class is new to Windows 8.1

The following code adds a new entry to the settings pane called Privacy policy and provides a handler for the command. In the handler we create a new instance of a SettingsFlayout and show it.

The text of the privacy policy is kept in a text file under the Settings folder. We asynchronously open and read the content of the file and when the text is available we create a new TextBlock control and use it as the content of the flyout content control.

Then we have to initialize the settings pane when the application starts.

When you start the application and swipe the right edge of the screen the charms bar shows up. Opening the Settings charm will now show two entries for the application: Privacy Policy and Permissions.
settingscharm2 settingscharm3

The next sample shows how to add an About page. It’s very similar actually.

Notice that the entries in the settings charm appear in the order they where added.
settingscharm4 settingscharm5

The content of the flyout can be any visual object (the simple TextBlock is used only for demo purposes). It is also possible to customize the flyout header, icon, background, etc. Here is the same About page with additional flyout settings.

settingscharm7

Here is some additional reading: Guidelines for app settings (Windows Store apps).

, , , , , Hits for this post: 7355 .

In WPF, Silverlight and Windows Phone it is possible to render a visual object into a bitmap using the RenderTargetBitmap. This functionality, that I find pretty basic, was not available for Windows Store applications. Fortunately, Windows 8.1 provides that functionality for Windows Store applications too, through the same RenderTargetBitmap class.

There are some limitations though:

  • it should be used in the code behind (not declared in XAML) because you have to call RenderAsync
  • collapsed visual objects are not rendered (only visible ones)
  • in rare circumstances the content can be lost due to the interaction with lower level systems; in this case a specific exception is triggered
  • the rendered target bitmap does not automatically scale when the current DPI settings change
  • the maximum rendered size of a XAML visual tree is restricted by the maximum dimensions of a DirectX texture

Here is a demo Windows Store application that has several controls and a button that when pressed a screenshot of the area shown in red (it’s a grid) is taken. The bitmap is saved on disk, but also displayed as the source for the image control shown in the preview area.

wsas1

The handler for the Click button even looks like this:

SaveScreenshotAsync is an async method that takes the reference to the FrameworkElement to be rendered to a bitmap (in this case the constrolsGrid) and returns a Task<RenderedTargetBitmap> that can be awaited on. As soon as we have the bitmap we set it as the source for the image control (imagePreview).

wsas2

SaveScreenshotAsync is an async method that takes the FrameworkElement to be rendered to a bitmap and returns a Task<RenderedTargetBitmap> that can be awaited on. This method first prompts the user to select a destination file for the rendered bitmap. When the file is available it calls SaveToFileAsync to rendered the bitmap and write it to the file.

SaveToFileAsync is an async method that takes the FrameworkElement to be rendered to a bitmap and the StorageFile when the bitmap is to be saved and returns a Task<RenderedTargetBitmap> that can be awaited on. The file is opened asynchronous for read-write access and the returned IRandomAccessStream is passed further together with the framework element and the bitmap encoder id (that specifies how the bitmap should be encoded, i.e. BMP, JPEG, PNG, GIF, etc.) to CaptureToStreamAsync.

CaptureToStreamAsync creates a new RenderTargetBitmap object and calls RenderAsync to render the visual tree of the framework element to a bitmap. After the bitmap is rendered it retries the image as a buffer of byes in the BGRA8 format. It then asynchronously creates a BitmapEncoder for the IRandomAccessStream stream that it received as an argument, it calls SetPixelData to set the pixels data (notice the BitmapPixelFormat.Bgra8 parameter that matches the pixels format returned by GetPixelsAsync) and later asynchronously flushes all the image data, basically writing it to the file. It then returns that RenderTargetBitmap object that it created, which is used eventually as the source for the image control.

Here is how the saved JPEG image (also seen in the preview screenshot above) looks likes:
wsas3

You can check the source code of the attached WinRT Screenshot demo (332). It requires Visual Studio 2013 and Windows 8.1.

, , , , , , Hits for this post: 8425 .

A friend of mine recently proposed the following problem on twitter:

I didn’t pay much attention to his warning and fell for the trap. I though I could write a small program in two minutes to compute the series and find what was the value of x[80]. So here is (a slightly modified version of) the C++ code that I put together in a couple of minutes.

C++

When I ran it I was surprised to notice that the series was converging to 100 by x[26].

Actually, the initial program didn’t call std::setprecision and the numbers you get without that are less precise, but that doesn’t change the convergence, since it is just a printing artifact.

Finding the series interesting I searched a bit and then I understood his warning. I found this was a well known problem proposed around 1980 by Jean-Michel Muller and discussed in several papers by Prof. W. Kahan.

Given the function
Œ(y, z) := 108 – ( 815 – 1500/z )/y
and initial values x0 := 4 and x1 := 4.25 , define xn+1 := Œ(xn, xn-1) for n = 1, 2, 3, … in turn.
Our task is to compute xN for some moderately big preassigned integer N, say N = 80 .

For details see How Futile are Mindless Assessments of Roundoff in Floating-Point Computation? and Three Problems for Math.

This exercise is intended to show the problem that arises in using floating-point numbers. The float and double (both an IEEE Standard for Floating-Point Arithmetic, IEEE 754) representations use inverse powers of 2, which means most numbers require a an infinite number of bits for a precise representation. Numbers such as 0.25 or 0.875 can be exactly encoded as 1/4 and 1/2+1/4+1/8, but numbers such as 0.10 cannot be encoded with a finite sum of such terms. The result is problems with accuracy of calculations. Rand-offs can propagate through calculations in unexpected ways, just like Muller’s recurrence shows.

The actual limit of Muller’s series is not 100, but 5.

I was curios then how the decimal type from .NET compares to double. decimal (that uses base 10 instead of 2) has more precision (but a smaller range) than float or double which makes is more suitable for some applications, such as financial ones. (For a discussion of when to use decimal and when to use double see decimal vs double! – Which one should I use and when?).

So here is my C# program that uses decimal.

The output of this program is:

This represents and improvement, but in the end suffers from the same accumulated round-offs problem. It takes more iterations, but eventually the series also converges to 100.

My friend then suggested trying a data type that doesn’t suffer from rounding issues. Such a type is BigRational for F# (it can be used with any .NET language). It is available in the F# PowerPack that is an open-source project available on CodePlex. Below is the F# equivalent of the previous program that uses BigRational.

The output looks like this:

Now this is a totally different story. The values converge to the expected value of 5.

You probably noticed the casting to double for printing. It is necessary because otherwise the output would look like this:

That isn’t very helpful. I can’t even read these insane large numbers, not to mention dividing them. So to get the actual real number and be able to compare with the previous programs a conversion to double is necessary.

As I mentioned earlier, BigRational can also be used from C#.

It yields the very same output as the F# program so I will not list it again. However, below is a comparison table with the results for various number data types.

index C++ with float C++/C# with double C# with decimal C#/F# with BigRational
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
4
4.25
4.47058868408203
4.64474487304688
4.77070617675781
4.85921478271484
4.98312377929688
6.39543151855469
27.6326293945313
86.9937591552734
99.2555084228516
99.9625854492188
99.9981307983398
99.9999084472656
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
4
4.25
4.47058823529412
4.64473684210522
4.77053824362508
4.85570071256856
4.91084749866063
4.94553739553051
4.966962408041
4.98004220429301
4.98790923279579
4.99136264131455
4.96745509555227
4.42969049830883
-7.81723657845932
168.939167671065
102.039963152059
100.09994751625
100.004992040972
100.000249579237
100.00001247862
100.000000623922
100.000000031196
100.00000000156
100.000000000078
100.000000000004
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
4
4.25
4.47058823529411764705882353
4.64473684210526315789473686
4.77053824362606232294617603
4.85570071258907363420428376
4.91084749908279320044042857
4.94553740412391672477683015
4.96696258176270059878160878
4.98004570135563116267108889
4.98797944847839228829979003
4.99277028806206866201151005
4.99565589150664533306792637
4.99739126838157043427422171
4.99843394394934565979621707
4.99906007206149646425952424
4.99943593895922460992955065
4.99966156035548033890851805
4.99979762579572007199519838
4.99989263769854913604459541
5.00021692999623515255759378
5.00575688343630115907717069
5.11585535860978057839952266
7.26513170553842597520695497
36.178328937337879304087182981
91.17958879988455033108590199
99.51631713443793014723080822
99.97569833055963020623148188
99.99878462167868201734350518
99.99993923036059445960870932
99.99999696151664049461733529
99.99999984807584112595945239
99.99999999240379245628007687
99.99999999962018963513083004
99.99999999998100948212683970
99.99999999999905047411745292
99.99999999999995252370620598
99.99999999999999762618532030
99.99999999999999988130926632
99.99999999999999999406546333
99.99999999999999999970327317
99.99999999999999999998516366
99.99999999999999999999925818
99.99999999999999999999996291
99.99999999999999999999999815
99.99999999999999999999999991
100.00000000000000000000000000
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
100
4
4.25
4.47058823529412
4.64473684210526
4.77053824362606
4.85570071258907
4.91084749908279
4.94553740412392
4.9669625817627
4.98004570135563
4.98797944847839
4.99277028806207
4.99565589150663
4.99739126838134
4.99843394394482
4.99906007197089
4.99943593714684
4.99966152410377
4.99979690071342
4.99987813547793
4.9999268795046
4.99995612706116
4.99997367600571
4.99998420552027
4.99999052328223
4.99999431395856
4.99999658837126
4.99999795302136
4.99999877181231
4.99999926308721
4.99999955785226
4.99999973471133
4.99999984082679
4.99999990449607
4.99999994269764
4.99999996561859
4.99999997937115
4.99999998762269
4.99999999257362
4.99999999554417
4.9999999973265
4.9999999983959
4.99999999903754
4.99999999942252
4.99999999965351
4.99999999979211
4.99999999987527
4.99999999992516
4.9999999999551
4.99999999997306
4.99999999998384
4.9999999999903
4.99999999999418
4.99999999999651
4.9999999999979
4.99999999999874
4.99999999999925
4.99999999999955
4.99999999999973
4.99999999999984
4.9999999999999
4.99999999999994
4.99999999999996
4.99999999999998
4.99999999999999
4.99999999999999
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5

The conclusion is that you should be aware that round-offs can accumulate and lead to unexpected results. Use the most appropriate data types suitable. Do not use double (not to mention float) for financial data.

, , , , , , , , Hits for this post: 7100 .

Speed-up VC++ builds

The larger a VC++ project is (or any project for that matter) the more time it takes to build. If you have solutions with many large projects the build times could get into your way. Starting a rebuild and going to lunch was a common scenario for me, as building took 20-25 minutes. Of course, you don’t rebuild everything all the time, but sometimes is enough to change something in a header somewhere deep inside the dependency web and trigger a rebuild of many or all the projects in a solution.

Using compiler switches and other tricks I managed to reduce the build time with about 50% or more (the percent of speedup is similar on different machines, regardless of the previous build times on those machines). Replacing the hard disk with an SSD provided an additional 25% speed. My full build times have decreased from 20-25 minutes to about 7 minutes.

First off all, Visual Studio enables parallel projects builds by default. As long as your projects don’t have dependency and can be built in parallel, it is possible to have up to 32 projects built at the same time. By default the number of projects built in parallel is set to the number of available cores. This option can be change from Tools > Options > Projects and Solutions > Build and Run.

vcbuild1

The VC++ compiler also supports multi-processor compilation. This can be enabled with a compiler switch, /MP. The result of this switch is that the compiler spawns into additional processes that simultaneous compile the source files. This option can be set per project from Project > Properties > Configuration Properties > C/C++ > General.

vcbuild2

This option is however incompatible with several compiler and language features. In case of incompatibility the behavior differs:

  • if the incompatibility is with another compiler option a warning is displayed and the /MP options is ignored
  • if the incompatibility is with a language feature an error is issued and compilation stops or continues depending on the error level

The incompatible features are: #import processor directive, /GM (enables incremental build), /Yc (writes a precompiled header file), /E and /EP (copies pre-processor output to the standard console), /showIncludes (writes a list of include files to the standard error console). These features are incompatible with /MP because they would imply shared resources (console or file) to be used possible at the same time from different processes.

The workaround for the #import processor directive is to move the directives to a file that is not built with the /MP option. However, in practice I had problems with that and the workaround that actually worked was to move the #import directives to the pre-compiled header. That is built (the corresponding source file actually) synchronously before the compilation of any other translation unit starts, so there are no incompatibilities. However, this has the drawback that any change in the imported type library will trigger a rebuild of the precompiled header and of the whole project.

vcbuild3

Below is a table of full build times for various VC++ projects from the same solution. The values were reported by MSBuild. The actual time values (shown to hundredths of a second) are not important (as they vary across builds and machines). What is important is the speed-up before enabling /MP and after it.

Before After
Release Debug Release Debug
00:00:58.43 00:00:53.14 00:00:37.32 00:00:25.23
00:00:45.41 00:00:33.25 00:00:12.16 00:00:07.47
00:00:56.85 00:00:54.90 00:00:51.35 00:00:50.72
00:00:45.41 00:00:44.34 00:00:24.41 00:00:20.16
00:01:00.92 00:01:05.97 00:01:15.40 00:01:14.07
00:04:17.89 00:04:25.88 00:01:34.66 00:01:17.97
00:02:59.41 00:02:26.42 00:01:11.99 00:00:54.07
00:00:46.96 00:00:43.96 00:00:17.70 00:00:17.41
00:00:46.05 00:00:46.05 00:00:16.69 00:00:14.40
00:01:44.84 00:01:35.11 00:00:30.29 00:00:28.13
00:00:11.02 00:00:14.26 00:00:07.97 00:00:08.24
00:00:09.28 00:00:12.75 00:00:07.59 00:00:07.59
00:00:08.46 00:00:08.95 00:00:10.89 00:00:08.25
00:00:18.68 00:00:19.79 00:00:14.32 00:00:11.35
00:02:46.37 00:00:50.76 00:01:52.16 00:00:28.88
00:00:13.87 00:00:11.66 00:00:09.24 00:00:11.06
00:01:05.37 00:00:54.76 00:00:25.45 00:00:26.83
00:00:29.00 00:00:16.68 00:00:13.32 00:00:12.94
00:00:25.79 00:00:14.05 00:00:12.09 00:00:12.04
00:00:22.80 00:00:11.50 00:00:11.60 00:00:11.93
00:00:31.76 00:00:39.33 00:00:25.00 00:00:21.19
00:00:56.01 00:00:59.04 00:00:26.62 00:00:23.95
00:00:20.40 00:00:12.92 00:00:08.64 00:00:07.99
00:00:16.48 00:00:18.61 00:00:09.18 00:00:08.71
00:00:09.74 00:00:10.49 00:00:06.84 00:00:09.84

Another strategy for increasing the build times is to reduce the number of times framework headers (STL, MFC, ATL, etc.) or headers from your project that do not change often and are included in many places are included into the various source files of your projects. These headers can be put in the pre-compilead header, and therefore compiled just once.

The next table shows the additional speed-up gain for several projects after moving framework headers to the pre-compiled header of each project.

Before After
Release Debug Release Debug
00:00:37.32 00:00:25.23 00:00:32.79 00:00:19.24
00:00:12.16 00:00:07.47 00:00:04.90 00:00:02.41
00:00:51.35 00:00:50.72 00:00:44.15 00:00:37.25
00:00:24.41 00:00:20.16 00:00:20.19 00:00:20.16
00:01:15.40 00:01:14.07 00:01:14.10 00:01:10.56
00:01:34.66 00:01:17.97 00:01:23.60 00:01:22.15
00:01:11.99 00:00:54.07 00:01:11.70 00:00:43.20

The speed-up gain by using these techniques may vary depending on your project specifics. In some cases the gain may not be significant or the build time may actually increase. You should play around with these settings and enable them only when they help you.

In summary, some of the strategies that can help increase your build times are:

  • break dependencies between projects they can be built in parallel
  • if you have large projects try to break them in smaller, independent projects; the more such projects you have the more work can be done in parallel
  • use multi-processor compilation (/MP) for C++ projects to enable compiling multiple translation units at the same time
  • move framework headers (STL, MFC, ATL, etc.) and other headers that do not change and are included all over your project to the pre-compiled header
  • use a SSD and keep your sources on it
, , , , , Hits for this post: 7620 .

Many years ago I published on my blog a helper class for working with the Windows console that was wrapping the Windows console API. Looking back at it I realized it was a pretty naive implementation. So I decided to start a new and make something more flexible and easier to use. Hopefully, I was more successful. The result is a small C++ template library called cppconlib, available on codeplex.

cppconlib is built with C++11 features and requires Visual Studio 2012 or newer. The library is available in a single header called conmanip.h and provides a set of helper classes, functions and constants for manipulating a Windows console (using the Windows console functions). The library features the following components:

  • console_context<T>: represents a context object for console operations; its main purpose is restoring console settings; typedefs for the three consoles are available (console_in_context, console_out_context and console_err_context)
  • console<T>: represents a console objects providing operations such as changing the foreground and background colors, the input mode, screen buffer size, title, and others; typedefs for the three consoles are available (console_in, console_out and console_err)
  • manipulating functions that can be used with cout/wcout and cin/wcin: settextcolor()/restoretextcolor(), setbgcolor()/restorebgcolor(), setcolors(), setmode()/clearmode(), setposx()/setposy()/setpos().

The library can be downloaded from here. Detailed documentation is available here.

cppconlib

Examples

The following example prints some text in custom colors and then reads text in a different set of colors.

cppconlib2

The following code prints a rhomb to the console:

cppconlib3

For more details and updates check the project at codeplex: https://cppconlib.codeplex.com.

UPDATE: A NuGet package for cppconlib is available.

, , , , , , , Hits for this post: 9737 .

In my previous post I shown how you can build a C++ application with the C++ REST SDK that fetches search results from a search engine. In this post I will go a step further and develop a client-server application from scratch using version 1.1.0 of the SDK. This version features an HTTP listener implementation (still in an experimental phase). Notice that for the time being this 1.1.0 SDK release does not work with Visual Studio 2013 Preview. This samples and built with Visual Studio 2012.

Overview of the problem to solve

The server manages a dictionary of key-value pairs (both strings) and supports several HTTP request methods:

  • GET: retrieves all the key-value pair from the dictionary.
    The response is a JSON object representing key-value pairs (eg. {"one" : "100", "two" : "200"}).
  • POST: retrieves the values of the specified keys from the dictionary.
    The request is a JSON array of strings (eg. ["one", "two", "three"]).
    The response is similar to the GET method, except that only requested keys are returned.
  • PUT: inserts new pairs of key-values in the dictionary. If a key is already found its value is updated.
    The request is a JSON object representing pairs of keys and values (eg. {"one" : "100", "two" : "200"})
    The response is a JSON object representing they key and the result for the action, such as addition or update (eg. {"one" : "<put>", "two" : "<updated>"}).
  • DEL: deletes the specified keys from the dictionary.
    The request is a JSON array of strings (eg. ["one", "two", "three"]).
    The response is a JSON object representing they key and the result for the action, such as success or failure (eg. {"one" : "<deleted>", "two" : "<failed>"}).

Notice that the server implements both GET and POST. The GET method is supposed to request a representation of the specified URI. Though it is theoretically possible that a GET request carries a body, in practice that should be ignored. The C++ REST library actually triggers an exception if you make a GET request with a body. Therefore, GET is used to return the entire content of the dictionary and the POST method, that supports a body, returns only the requested key-value pairs.

The client can make HTTP requests to the server, adding or updating key-values, fetch or delete existing pairs.

All communication, both for the request and the answer, is done using JSON values.

The server implementation

On the server side we have to do the following:

  • instantiate an http_listener object, specifying the URI where it should listen for requests.
  • provide handlers for the HTTP request methods for the listener.
  • open the listener and loop to wait for messages.

The core of the server application is shown below (except for the request handlers).

In this simple implementation the dictionary is a std::map. Its content is not persisted to disk, it is reloaded each time the server starts.

Let’s now look at the handlers. As mentioned earlier the GET method is a bit different than the others. A GET request should return all the key-value pairs in the server’s dictionary. Its implementation looks like this:

What it does is iterating through the dictionary and putting its key-value pairs into a json::value::field_map. That object is then sent back the the client.

The POST, PUT and DEL methods are a bit more complicated, because they all receive a JSON value specifying either keys to fetch or delete or pairs of key-value to add or update in the dictionary. Since some code would get duplicated several times I have created a generic method for handling requests that takes a function that evaluates the JSON request value and builds the response JSON value.

The handlers for POST, PUT and DEL will then call this generic method providing a lambda with the actual core implementation of each request handling.

And that is all with the server.

The client implementation

On the client side we need a http_client object to make HTTP requests to the server. It has an overloaded method request() that allows specifying the request method, a path and a JSON value for instance. A JSON value is not sent if the method is GET (or HEAD). Since for each request the answer is a JSON value, I have created a method called make_request() that dispatches the request and when the response arrives it fetches the JSON value and displays it in the console.

The core of the client code looks like this:

In the main() function I then just make a series of requests to the server, putting, fetching and deleting key-values from the server’s dictionary.

The client and server in action

You need to start the server first and then run the client. The output from running the client is:

On the server console the output is:

, , , , , , Hits for this post: 10635 .