C++ Inversion Of Control (IOC) Container

by billkrat 30. March 2014 12:29

IOC, aka dependency injection, is an important component to building decoupled, composite applications.  One of the first objectives I have to complete as I learn modern C++ is to create a data layer – it is a fundamental requirement.  

I opted to create an ADO.NET style wrapper as it is familiar to myself, as well as most C# developers.  The business logic layer will communicate with the data layer via its interface which will permit me to swap out the data layer programmatically, i.e., I can use a SQLite implementation for my phone when it cannot connect to Azure but if I later get a connection I can switch to the Azure implementation – of course I’d sync any work done offline behind the scenes.

I’m coming to really enjoy modern C++ as it lends itself to this nicely.  My “poor mans IOC” container supports registration of types (lines 27 and 67), named types (lines 26, 48, 68, and 69), and singletons (line 49).  TDD asserts that I get expected results.  I like the fact that I can abstract away the complexity of working with shared_ptr and namespaces via “using declarations” – the code doesn’t look that much different from C#.

I call it a “poor mans IOC” because I am a newbie C++ developer and while I can make it walk and talk, I can’t make it dance so within the context of agile development I am starting with the basics; it doesn’t support setter or constructor injection however like Microsoft’s Unity I do have a BuildUp() method – it is through this that I can propagate the dependency chain.  For example…

I opted to override the BuildUp() method in my MockWidget (top right pane line 17) and define it on in the bottom right pane on lines 38 thru 48.   This permits my MockWidget to Resolve (instantiate) any interface within the container, in this case I want to resolve the named interface ITest (line 42 bottom right).    Once it instantiates it, it retrieves its Id (random generated value) and the HelloWorld() results which vary from implementation to implementation (lines 74-76 on left pane)

The MockWidget BuildUp has no knowledge of its implementation, only that ITest has a HelloWorld() method and an Id field.  It is complete decoupled and has no knowledge of its implementation - which in this case is the MockHelloWorld class (registered on line 26 in left pane).  I could swap it out for any implementation of ITest without impacting the application at all.

This is why TDD becomes important.  I will write comprehensive test for my SQLite implementation and later (when it is done) will create my Azure implementation and plug it in – at this point all of the test will fail and I will complete the Azure implementation until all test pass. Once they do I can swap it out without changing a line of code in what could be hundreds to thousands of lines of code – for multiple applications.

IOC-ITest

Tags: ,

IOC

C++ It’s the little things in life…. a living document.

by billkrat 30. March 2014 05:18

In my journey to learn C++ I document the head-bangers, particularly the ones that took hours of my life that I will never get back.  There are some issues that don’t warrant their own blog but are blog worthy, at least to folks new to C++ so I’d like to get it documented before I also become far removed from my ignorance and see this as basic stuff (assumed to be known by all).  This will be a “living document” in the sense that I will continue to add things as I encounter them.

Source code referenced will most likely be from my open source project http://PasswordMgr.CodePlex.com



error LNK2001: unresolved external symbol "public: static int DebugLogger::RefCount"

class DebugLogger : public ILogger
{
public:
static int RefCount;

DebugLogger();
~DebugLogger();
wstring Log(const string message, ...) override;
wstring Log(const wstring message, ...) override;
};

I stumbled on this error because RefCount is a field – it seemed odd that I would have to define it in addition to the declaration…  Sure enough, once I added the following definition my code compiled again.

image


error C2065: 'IServiceLocator' : undeclared identifier

image

I see this one quite a bit, I suspect most C# developers will at first.  The problem is that I failed to #include “IServiceLocator.h”,  the IDE won’t help you on this one.  I reported this as a Microsoft Bug 785188, from their response it most likely won’t be fixed anytime soon (or at all).   So yes, according to the IDE there are no issues with the following code – that is until you attempt to compile.


Intellisense does not work – build is successful

image

This one stumped me for a while….  Turns out this is closely related to the prior entry (above).  I discovered I did not have an include for the IServiceLocator and once I added it my intellisense started working as expected.

image


C++ Casting shared_ptr to base and derived classes

by billkrat 29. March 2014 19:33

SOURCE CODE: http://PasswordMgr.CodePlex.com (changeset 105567)

As the smoke settled on what will be the standard for my infrastructure I realized that it may offend the sensibility of C++ developers and be foreign to C# developers – HOWEVER, I suspect that like me C# developers will be able to wrap their head around the code a lot faster with just a few tips, they follow:

  • using declaration – If you look at the middle pane of figure 2 you will see the using declarations that I adopted as the standard for representing the _Object baseclass (which derives from Type).   Note: the _Object baseclass will raise an eyebrow or two from C++ developers (and be frowned upon) and will most likely be embraced by C# developers.  The simplicity of my Inversion Of Control (IOC), aka Dependency Injection, container relies on it; my decoupled composite framework (which I am building) demands it.
  • Templates (loosely similar to generics for C# developers) - Line 34 will seem cryptic to C# developers but just look at it as the C++ way of specifying generic types; they just put it before the method (in a rather verbose manner) versus at the end of the method name.   So for C# we would have done the following for line 34 and 35:   PoorMansIoc* Register<TInterface, TService>()
  • Instantiating / Initializing new classes – C# developers will find that there are many ways to instantiate and initialize classes.  The books I’ve read don’t suggest there is any best practice and pattern other than you be consistent.  So my consistent method will be to use brackets { }.    So line 38 is equivalent to the following C# code: var value = new SharedObject( (object) new TService() );
  • Pointers – one of the biggest learning curves (for me) comes from the fact that we as C# developers are used to passing things around by reference where C++ developers are use to passing by value.  I try to abstract this away as much as possible – lines 26, 35, and 43 are necessary evils and beyond the scope of this blog.

SharedSample
Figure 1 excerpt from the PoorMansIoc container Register method

With that said the following TDD on the left should not be as intimidating to C# developers.

Where all of the modern C++ books tell us we need to use shared_ptr<class>(new class) so that our code will be memory and exception safe (meaning that no dangling pointers/memory will be left on errors); none of them that I could find tell us how to cast them so that we can use base classes effectively.

Fortunately I found the a reference to dynamic_pointer_cast on MSDN at this link which helped me achieve my goals.

Generally when we look at a class hierarchy we start with the base classes at the top and derived classes below them.  In C++ you’ll see terms such as upcasting and downcasting which is relative to this assumption (ref lines 16-26 in figure 2, left pane).

On line 30 I was happy to see that we could do a cast in a manner that is familiar to us C# developers, in the C++ world this would be a more verbose reinterpret_cast<Object> versus a simple (Object) statement.   This allowed me to create a shared_ptr<_Object*>(new MockHelloWorld()) – my first successful cast; I now have an Object that I can store in a list of Objects.

On lines 36 I need to take these Objects and cast them to an Interface ITest (downcasting).  This is what the dynamic_pointer_cast was designed for.

Something C# developers will feel at home with is Type and the GetType() method.   Notice that I even threw in an Activator::CreateInstance<T>(Type) which will create a new instance of Type – a shared_ptr<T>(Type).

Code
Figure 2 TDD for upcasting and downcasting

C++ fatal error LNK1169: one or more multiply defined symbols found. Keeping declarations (.h) separate from definitions (.cpp)

by billkrat 29. March 2014 13:49

I added a new unit test fixture for developing my System components,  after simply adding my header I was greeted with this error; it was complaining that the MockHelloWorld methods were already defined in my PoorMansIocFixture unit test.

Error

The lesson I learned on this adventure was not to mix my declarations (.h) with my definitions (.cpp).  I did this because they are just mock classes for testing purposes and I wanted to save time. 

Once I moved all of the definitions (for the three mock classes lines 2-4 highlighted below) then all was well again!

Worky

C++ error C2504: base class undefined - how to resolve circular header reference

by billkrat 29. March 2014 11:48

Things we’re going smoothly as I prepared for my preliminary upload of source code; I have been performing TDD on an IOC container, logger, and basic framework and have enough done to make my first upload (I’ll be uploading it to my open source project at http://PasswordMgr.CodePlex.com.) 

I added two lines of code (pointed to by arrows in figure 1) which started me on my next adventure…

Just as C# won’t permit us to create a circular reference on project references, C++ won’t permit me to have a circular reference for header files.   I’m adding a GetInstance() method to the Type class which will be used by my poor mans IOC container; it needs an _Object reference which has us in a chicken-before-the-egg scenario.

Errora

The solution was very simple – all I had to do was remove the include “Object.h” and create a forward reference (highlighted on line 6 below).  After that everything compiled and all was good!

Worksa

Overloading the subscript operator in modern C++ (shared_ptr)

by billkrat 26. March 2014 19:36

This adventure ate my breakfast, lunch, and dinner for a few days…  The biggest problem is that all of my reference material consistently gives examples such as the one that follows:

image This would work great if I were trying to return an int or double because most, if not all, of the articles/books/blogs will demonstrate how easily this can be done using variations of the example on the left.

My problem started when I needed to overload the subscript operator to return a shared_ptr<DataColumn>.  This is where I left a bloody mess on my desktop as I banged my head against it trying to find a “modern” way – it wasn’t readily available and it cost me a few days….

So if you’re like me and don’t want to create get/set methods (and you ended up with the error caused by the subscript referenced by the arrow below) keep reading, I do have an easy answer (although it is quite ugly).

UnitTestSummary-2

The answer is to dereference first (highlighted content on lines 138-139) and then use the subscript operator to obtain your data references.  Likewise you can use the –>operator[] as shown on lines 151-156.

Note below (arrows) that my classes have static RefCount ints so that I can ensure I don’t leak memory as I build my ADO Style wrapper for Sqlite (http://msdn.microsoft.com/en-us/library/vstudio/hfx3s9wd(v=vs.100).aspx).  The notion being that as I code I can place asserts at points where I expect there to be no RefCounts for a given class (trap memory leaks when I break something).

UnitTestSummary

 
DataColumnFixture.cpp in its entirety (classes in test fixture during POC TDD):
#include "stdafx.h"
#include "CppUnitTest.h"
#include "ILogger.h"
#include "DebugLogger.h"
#include <vector>
#include <map>
#include <string>
#include <Windows.h>
#include <memory>
#include <sstream>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

extern void OutputDebugDateTime();

namespace lib
{
using std::string;
using std::vector;
using std::map;
using std::pair;
using std::shared_ptr;
using std::make_shared;
using std::stringstream;
}

// IOC Container stub -----------------------------
template <typename T>
static T Resolve() { return new DebugLogger(); }


// typeof() stub-----------------------------------
using type = string;
type typeof(string typeName) { return typeName; }
const string String = "String";
const string Int = "int";

namespace GwnDataLibTests
{
class DataColumn
{
bool isInitialized = false;
ILogger *logger{ Resolve<ILogger*>() };

public:
static int RefCount;
string Caption;
string ColumnName;
type Type;
int Ordinal;

DataColumn();
~DataColumn();
DataColumn(string caption, string columnName, type type, int ordinal);
};

int DataColumn::RefCount = 0;

DataColumn::DataColumn()
{
logger->Log("%d: +DataColumn()\r\n", ++RefCount);
}

DataColumn::DataColumn(string caption, string columnName, type type, int ordinal)
{
ColumnName = columnName;
Caption = caption;
Ordinal = ordinal;
Type = type;

logger->Log("%d: +DataColumn(\"%s\", \"%s\", %d)\r\n",
++RefCount, columnName.c_str(), type.c_str(), ordinal);
}

DataColumn::~DataColumn()
{
logger->Log("%d: ~DataColumn()\r\n", --RefCount);
delete logger;
}


class DataColumnCollection
{
int ordinal{ 0 };
DataColumn currentColumn;
lib::vector<lib::shared_ptr<DataColumn>> List;
lib::map<string, lib::shared_ptr<DataColumn>> columnFromName;
ILogger *logger{ Resolve<ILogger*>() };

public:
static int RefCount;
DataColumnCollection();
~DataColumnCollection();
lib::shared_ptr<DataColumn> operator[](int i);
const lib::shared_ptr<DataColumn> operator[](int i) const;
void Add(string columnName, type columnType);
};

int DataColumnCollection::RefCount = 0;

lib::shared_ptr<DataColumn> DataColumnCollection::operator[](int i)
{
return List[i];
}
const lib::shared_ptr<DataColumn> DataColumnCollection::operator[](int i) const
{
return List[i];
}

DataColumnCollection::DataColumnCollection()
{
logger->Log("%d: +DataColumnCollection()\r\n", ++RefCount);
}
DataColumnCollection::~DataColumnCollection()
{
logger->Log("%d: ~DataColumnCollection()\r\n",--RefCount);
delete logger;
}
void DataColumnCollection::Add(string columnName, type columnType)
{
logger->Log("\t Adding column %s typeof(%s)\r\n",
columnName.data(), columnType.data());

auto col = lib::shared_ptr<DataColumn>(
new DataColumn { "Caption", columnName, columnType, ordinal++ });
List.push_back(col);
columnFromName[columnName] = col;
}

TEST_CLASS(DataColumnFixture)
{
public:
TEST_METHOD(CanGetListIndex)
{
ILogger *logger{ Resolve<ILogger*>() };

if (true){ // Scope for shared ptrs so that destructors will kick in
logger->Log("\t Instantiating DataColumnCollection\r\n");

auto myTest = lib::make_shared<DataColumnCollection>();
myTest->Add("Name", typeof(String));
myTest->Add("Age", typeof(Int));

auto mt1 = (*myTest)[0]; // myTest->operator[](0);
auto mt2 = (*myTest)[1]; // myTest->operator[](1);

// Assert that we get expected results
Assert::AreEqual(string{ "Name" }, mt1->ColumnName);
Assert::AreEqual(typeof(String), mt1->Type);
Assert::AreEqual(0, mt1->Ordinal);

Assert::AreEqual(string{ "Age" }, mt2->ColumnName);
Assert::AreEqual(typeof(Int), mt2->Type);
Assert::AreEqual(1, mt2->Ordinal);

// An alternate way - doesn't look much better...
auto mt1a = myTest->operator[](0);
Assert::AreEqual(mt1->ColumnName, mt1a->ColumnName);
Assert::AreEqual(mt1->Type, mt1a->Type);
Assert::AreEqual(mt1->Ordinal, mt1a->Ordinal);

auto mt2a = myTest->operator[](1);
Assert::AreEqual(mt2->ColumnName, mt2a->ColumnName);
Assert::AreEqual(mt2->Type, mt2a->Type);
Assert::AreEqual(mt2->Ordinal, mt2a->Ordinal);
}
logger->Log("**************************\r\n");
logger->Log("DataColumn: %d\r\n", DataColumn::RefCount);
logger->Log("DataColumnCollection: %d\r\n ", DataColumnCollection::RefCount);
logger->Log("**************************\r\n");
delete logger;
}
};
}

ILogger.h

#pragma once
#include <string>
#include <Windows.h>

using std::string;
using std::wstring;

class ILogger
{
public:
wstring virtual Log(const string message, ...) = 0;
wstring virtual Log(const wstring message, ...) = 0;

virtual ~ILogger() = 0
{
OutputDebugString(L"~ILogger()\r\n");
}
};
 

DebugLogger.h
#pragma once
#include "ILogger.h"
#include <vector>

using std::wstring;

class DebugLogger : public ILogger
{
public:
static int RefCount;
DebugLogger();
~DebugLogger();

wstring Log(const string message, ...) override;
wstring Log(const wstring message, ...) override;
};

DebugLogger.cpp

#include "pch.h"
#include "DebugLogger.h"

#include <Windows.h>
#include <memory>
#include <string>

using std::wstring;
using std::vector;
using std::begin;
using std::end;

void OutputDebugDateTime()
{
string date{ __DATE__ };
string time{ __TIME__ };
string dateTime = date + " " + time;
wstring wDateTime(begin(dateTime), end(dateTime));
OutputDebugString(wDateTime.data());
OutputDebugString(L" ");
}

int DebugLogger::RefCount = 0;

DebugLogger::DebugLogger()
{
Log("%d: +DebugLogger()\r\n", ++RefCount);
}

DebugLogger::~DebugLogger()
{
Log("%d: ~DebugLogger() ", --RefCount);
}

wstring DebugLogger::Log(const string str, ...)
{
// Convert string to char*
auto formattedMessage = str.c_str();

// Use vector for buffer so we can resize if applicable
vector<char> buffer;

// Default size for buffer is twice size of str (parameter)
int sizeOfBuffer = str.size() * 2;
buffer.resize(sizeOfBuffer);

// Initialize our variable argument list. Note that
// for va_start we send the last parameter prior to ...
va_list argPtr;
va_start(argPtr, str);

// _vsnwprintf_s returns negative value if an output error
// occurs assumption is that buffer isn't big enough, we'll
// try abandon if failure continues.
auto counter = 0;
while (++counter < 4)
{
// format the string using variable arguments -> buffer
int ret = _vsnprintf_s(
buffer.data(), // char *buffer
sizeOfBuffer, // size_t sizeOfBuffer
_TRUNCATE, // size_t count
formattedMessage, // const char *format
argPtr // va_list argptr
);
if (ret != -1)
break;
else {
// Increase size of buffer - parameter size may be larger
// than the default allocation of 2 x str length
sizeOfBuffer *= 2;
buffer.resize(sizeOfBuffer);
}
}
va_end(argPtr);

// Convert buffer to wstring so we can easily get wchar_t*
// for the OutputDebugString(LPCWSTR*) parameter
wstring message(buffer.begin(), buffer.end());

OutputDebugDateTime();
OutputDebugString(message.data());
//OutputDebugString(L"\r\n");

return message;
}

wstring DebugLogger::Log(const wstring str, ...)
{
// Convert wstring to wchar_t*
const wchar_t* formattedMessage = str.data();

// Use vector for buffer so we can resize if applicable
vector<wchar_t> buffer;

// Default size for buffer is twice size of str (parameter)
auto sizeOfBuffer = wcslen(formattedMessage) * 2;
buffer.resize(sizeOfBuffer);

// Initialize our variable argument list. Note that
// for va_start we send the last parameter prior to ...
va_list argPtr;
va_start(argPtr, str);

// _vsnwprintf_s returns negative value if an output error
// occurs assumption is that buffer isn't big enough, we'll
// try abandon if failure continues.
auto counter = 0;
while (++counter < 4)
{
// format the string using variable arguments -> buffer
int ret = _vsnwprintf_s(
buffer.data(), // wchar_t *buffer
sizeOfBuffer, // size_t sizeOfBuffer
_TRUNCATE, // size_t count
formattedMessage, // const wchar_t *format
argPtr // va_list argptr
);
if (ret != -1)
break;
else
{
// Increase size of buffer - parameter size may be larger
// than the default allocation of 2 x str length
sizeOfBuffer *= 2;
buffer.resize(sizeOfBuffer);
}
}
va_end(argPtr);

// Convert buffer to wstring so we can easily get wchar_t*
// for the OutputDebugString(LPCWSTR*) parameter
wstring message(buffer.begin(), buffer.end());

OutputDebugDateTime();
OutputDebugString(message.data());
//OutputDebugString(L"\r\n");

return message;
}

Tags:

C# string.format for C++ / _vsnwprintf_s idiosyncrasies

by billkrat 23. March 2014 08:41

Lost many, many hours trying to figure out why my unit test was failing while performing TDD for my string.format() style support for my debug logger.  Turns out that _vsnwprintf_s and _vsnprintf_s methods are fragile, however with a little care we can bend them to our will.  One of the many lessons I learned during this adventure – don’t use a single parameter when performing TDD, I got it to work and then when I went to 2+ parameters…. CRASH.

 stringFormatError
figure 1 the top pane is during TDD and the bottom from application execution

The key to success is twofold. 

  1. Ensure your variable parameters (va_list) are consistent with the _vsnprintf_s or _vsnwprintf_s method that you are calling.  In my ignorance of this fact my early attempts using a single parameter resulted in question marks, e.g., “?????” being displayed.
  2. Only send supported types.  After much trial and error I discovered that string is not supported by either _vsnprintf or _vsnwprintf methods!  

Early successes had me using techniques shown on line 30 in figure 2 (right pane).   Where I was pleased to see it working I didn’t want to have to remember to add the .data() suffix to my variable parameter list (for strings).   I then added the overload wstring DebugLogger::Log(const wstring str, …) and found that I could have a cleaner experience as shown on line 35 in figure 2 (right pane).

The key is to ensure my first parameter is a wchar_t* or wstring so that the overload using _vsnwprintf_s() will be used, its parameters expect wchar_t* – as long as all strings match this all is well.

After taking the screenshot for figure 2 I added an integer (100) and updated the assert to ensure that I can mix strings with integers and get expected results (reference figure 3).

 stringFormatCode
figure 2 source code for DebugLogger


 image
figure 3 updated unit test to include an integer (100)

Header: DebugLogger.h

Interface: ILogger.h

C++ base classes, be sure to use virtual destructor!

by billkrat 23. March 2014 07:56

As a C# developer we don’t have to worry (as much) about memory management so the use of destructors may seem quite foreign to us.  Although C# supports them we’ve learned early that we cannot rely on them firing at any specific time, so best practices and patterns would have us not use them as this is managed by .NET garbage collection – instead we use the IDisposable pattern.

Unlike C#, C++ uses  Resource Acquisition Is Initialization (RAII) – this basically means that when a class instance loses scope its destructor will fire if there are no references to it.  

Since memory management is new to me (as a C# developer learning C++), a logger is going to be critical during initial learning periods, e.g., case in point I was surprised that my destructor did not fire for the unit test shown in figure 2 (right pane) after deleting the logger on line 42.  Coming out of the gate I had memory leak!

Fortunately the advice of one of the Microsoft C++ developers (that reviewed my MSDN April article) came to mind, he noted that I needed to ensure I had a virtual destructor, he didn’t elaborate on it – just said it was required.  So it seemed logical that might be why my DebugLogger destructor was not firing as I had nothing else that could be keeping it in memory.

My knee jerk reaction, based on my limited experience having learned that pure virtual functions was the way to go for abstract classes (most equivalent to our interfaces for multiple inheritance), was to create a pure virtual destructor, e.g.,

~ ILogger() = 0;

Where the “=0” suffix is equivalent to the “abstract” prefix we C# developers use to create our abstract classes.  However, I was greeted with the following error:

5>GwnCommonLib.lib(DebugLogger.obj) : error LNK2019: unresolved external symbol "public: virtual __thiscall ILogger::~ILogger(void)" (??1ILogger@@UAE@XZ) referenced in function "public: virtual __thiscall DebugLogger::~DebugLogger(void)" (??1DebugLogger@@UAE@XZ)

So after reviewing “The C++ Programming Language, Forth Edition”, by Bjarne Stroustrup, I see that he has us using a virtual destructor (not a pure virtual using “=0”) so once I made it a virtual function (ref figure 2, left pane, lines 14-17) everything worked as expected.  If you’ll reference the output window in the bottom right pane of figure 2 you’ll see we highlighted the logger output that shows both destructors for our DebugLogger and its baseclass (ILogger) have fired as we expected.

NoWorkyVirtualDestructorForBase
figure 1 Our DebugLogger failed to destruct – we have a memory leak…

VirtualDestructorForBase
figure 2 everything is working as expected – DebugLogger and its base (ILogger) have their destructors fire.