Statically Linked Qt On Win32 Using MSVC

I have been trying to compile a statically linked version of Qt on Windows using MSVC for some time now but never found my way through until recently. There is a lot of information on the web about how to do this however I haven’t found one that actually worked for me (some information can be found on Trolltech’s website). So here’s yet another howto for using a static version of Qt with Visual Studio 2008!

What you need:

What you do (assuming VS2008 is already installed):

  1. Unpack the Qt sources. I used C:\Qt\4.5.3-win32-msvc2008 as target (%QTDIR%)
  2. If you have a multicore CPU you might want to speedup things by modifying %QTDIR%\mkspecs\win32-msvc2008\qmake.conf and adding those two lines (change 2 for the no. of CPUs you have):
    QMAKE_CXXFLAGS_RELEASE += -MP2
    QMAKE_CXXFLAGS_DEBUG += -MP2
  3. Next, open a Visual Studio 2008 Command Prompt (under the Start menu), go to %QTDIR% and run configure.exe with at least -static as option. I used the following (minimal build):
  4. configure.exe -debug-and-release -opensource -static -no-exceptions -no-accessibility -no-stl -no-qt3support -no-opengl -platform win32-msvc2008 -qt-zlib -qt-gif -qt-libpng -qt-libmng -qt-libtiff -qt-libjpeg -no-openssl -no-dbus -no-phonon -no-webkit -no-scripttools

  5. Once configured, start the build:
    nmake sub-src
  6. Install the Qt Visual Studio Addin
  7. In Visual Studio, under the Qt menu choose Qt Options. Under the Qt Versions tab click Add and type 4.5.3_win32-msvc2008 (or whatever you want) and fill in the path where you extracted the Qt sources
  8. Optionally you can test your installation by creating a new Qt Project, compiling it and running it.

Easy enough?! Happy Qt’ing!

UPDATE 15/10/2009: This also works with MS Visual Studio C++ Express Edition!

Advertisements

Reference Counting Garbage Collection

One nice feature from the .NET world is garbage collection. You simply don’t need to worry (99% of the time) about memory allocation resulting from creating new objects. The .NET garbage collector detects when an object is no longer needed based on a few heuristics but mainly based on reference count.

Using the same technique while using C++ is possible, and even easy. Since programming is about reuse I opted to create a class that wraps existing objects to add the wanted feature. It looks like this:

CRefObject<TExisting>* p = CRefObject<TExisting>::CreateInstance(/* TExisting ctor args */);

CRefObject basically derives from TExisting to keep all the same functionality:

template<typename TBase, typename TActivator = CRefActivatorTraits<TBase>>
class CRefObject : public TBase
{

...

};

Keeping the reference count within the object itself is important as one objective is to pass objects between threads without having to worry about memory allocation. There are many smart pointers out there and many implement reference counting however I haven’t found one that keeps the reference count as an part of an object identity.

Implementing CRefObject<T> is quite straightforward: manage reference counting.

	ULONG AddRef()
	{
		return ::InterlockedIncrement(&m_lRefCount);
	}

	ULONG Release()
	{
		LONG lCount = ::InterlockedDecrement(&m_lRefCount);
		ATLASSERT(lCount >= 0);
		if (lCount == 0)
			TActivator::Destroy(this);

		return lCount;
	}

Now that we have reference counting we can upgrade existing objects and manage reference counting like this:

CRefObject<TExisting>* p = CRefObject<TExisting>::CreateInstance(/* TExisting ctor args */);
...
// When done with the object, release it
p->Release();

That looks like COM doesn’t it? Yes it does. And there is one more feature we can add to make it look even more like COM using ATL: using smart pointers. This makes it much easier to track the reference count. Welcome CRefAutoPtr<T>:

template<typename T>
class CRefAutoPtr
{
public:
	CRefAutoPtr() throw() :
		m_pT(NULL)
	{ }

	CRefAutoPtr(const CRefAutoPtr& sp) throw() :
		m_pT(sp.m_pT)
	{
		_AddRef();
	}

	explicit CRefAutoPtr(CRefObject* pT) throw() :
		m_pT(NULL)
	{
		_Attach(pT);
	}

	virtual ~CRefAutoPtr() throw()
	{
		_Release();
	}

	CRefAutoPtr& operator =(const CRefAutoPtr& sp) throw()
	{
		_Release();
		m_pT = sp.m_pT;
		_AddRef();
		return *this;
	}

	CRefObject* operator &() throw()
	{
		_AddRef();
		return m_pT;
	}

	operator CRefObject*() throw()
	{
		return operator&();
	}

	CRefObject* operator ->() const throw()
	{
		return m_pT;
	}

	bool operator !=(const CRefAutoPtr& sp) const throw()
	{
		return !operator==(sp);
	}

	bool operator ==(const CRefAutoPtr& sp) const throw()
	{
		return m_pT == sp.m_pT;
	}

	CRefObject* Detach() throw()
	{
		CRefObject* pT = m_pT;
		m_pT = NULL;
		return pT;
	}

protected:
	VOID _Attach(CRefObject* pT) throw()
	{
		_Release();
		m_pT = pT;
	}

	VOID _AddRef() throw()
	{
		CRefObject* pT = m_pT;
		if (pT)
			pT->AddRef();
	}

	VOID _Release() throw()
	{
		CRefObject* pT = m_pT;
		if (pT)
		{
			m_pT = NULL;
			pT->Release();
		}
	}

public:
	CRefObject* m_pT;
};

The whole implementation isn’t 100% complete, but its quite a good start.

Byte Formatting Revisited

If you read my last post you may have noticed both ConvertBytes and FormatBytes could benefit a few improvements. After thinking the implementation over again I made the following improvements.

  1. The biggest change is the order of the parameters in both functions; in order to allow for default parameters I moved the out parameters (pointers) to the beginning of the parameter list
  2. In ConvertBytes instead of linking the binary prefix to the exponent I now use a different variable for less confusion
  3. If the provided size is already below the base then the output binary prefix is set to BP_NONE
  4. I renamed iPrefix to iBinaryPrefix in both functions for consistency
  5. In FormatBytes I now use the new BP_NONE output prefix
  6. Formatting has been changed to 2 decimals instead of 3 (can be specified otherwise)
  7. An extra parameter has been added to FormatBytes for specifying whether the binary prefix is to appear in the fomatting (i.e. useful when formatting a range of bytes; e.g. 5.6-9.1 KB)
  8. Finally, FormatBytes now handles formatting provided bytes if below the base (i.e. using B)

Here’s what both functions now look like:

enum PREFIXNORM
{
	PN_SI,					// Base 10 (i.e. 1000)
	PN_IEC,					// Base 2 (i.e. 1024)
	PN_DECIMAL = PN_SI,
	PN_BINARY = PN_IEC
};

const INT iPrefixBase[] = { 1000, 1024 };

enum BINARYPREFIX
{
	BP_NONE = -2,
	BP_AUTO,
//	SI				IEC 60027	Exp (b10/b2)	Exp (b1000/b1024)
	BP_KILO,		// KIBI		3				1
	BP_MEGA,		// MEBI		6				2
	BP_GIGA,		// GIBI		9				3
	BP_TERA,		// TEBI		12				4
	BP_PETA,		// PEBI		15				5
	BP_EXA,			// EXBI		18				6
	BP_ZETTA,		// ZEBI		21				7
	BP_YOTTA		// YOBI		24				8
};

const LPTSTR pszPrefixes[][8] = {
	{ _T("KB"),  _T("MB"),  _T("GB"),  _T("TB"),  _T("PB"),  _T("EB"),  _T("ZB"),  _T("YB") },
	{ _T("KiB"), _T("MiB"), _T("GiB"), _T("TiB"), _T("PiB"), _T("EiB"), _T("ZiB"), _T("YiB") },
};

typedef DOUBLE *LPDOUBLE;
typedef BINARYPREFIX *LPBINARYPREFIX;

BOOL ConvertBytes(
	LPDOUBLE pdResult,
	LPBINARYPREFIX piBinaryPrefix,
	ULONGLONG ullBytes,
	BINARYPREFIX iBinaryPrefix = BP_AUTO,
	PREFIXNORM iPrefixNorm = PN_DECIMAL)
{
	if (!pdResult || !piBinaryPrefix)
		return FALSE;

	DOUBLE dSize = (DOUBLE)ullBytes;
	DOUBLE dBase = (FLOAT)iPrefixBase[iPrefixNorm];

	*pdResult = dSize;
	*piBinaryPrefix = iBinaryPrefix;

	if (iBinaryPrefix == BP_NONE)	// No conversion required
		return TRUE;

	DOUBLE dExponent = 0;

	if (iBinaryPrefix == BP_AUTO) // Try to find a suitable prefix
	{
		if (dSize < dBase)
		{
			*piBinaryPrefix = BP_NONE;
		}
		else
		{
			dExponent = ::floor(::log(dSize) / ::log(dBase));
			*piBinaryPrefix = (BINARYPREFIX)((INT)dExponent - 1);
		}
	}
	else					// Use provided prefix
	{
		dExponent = iBinaryPrefix + 1;
	}

	*pdResult = dSize / ::pow(dBase, dExponent);

	return TRUE;
}

CString FormatBytes(
	LPBINARYPREFIX piBinaryPrefix,
	ULONGLONG ullBytes,
	BINARYPREFIX iBinaryPrefix = BP_AUTO,
	PREFIXNORM iPrefixNorm = PN_SI,
	INT iDecimals = 2,
	BOOL bFormatPrefix = TRUE)
{
	DOUBLE dResult;
	BOOL bRes = ::ConvertBytes(&dResult, piBinaryPrefix, ullBytes, iBinaryPrefix, iPrefixNorm);
	ATLASSERT(bRes);

	if (*piBinaryPrefix == BP_NONE || ullBytes < iPrefixBase[iPrefixNorm])
		iDecimals = 0;

	CString szFormat, szResult;
	szFormat.Format(_T("%%.%df"), iDecimals);

	if (bFormatPrefix)
	{
		if (*piBinaryPrefix == BP_NONE)
			szFormat.Append(_T(" B"));
		else
			szFormat.AppendFormat(_T(" %s"), pszPrefixes[iPrefixNorm][*piBinaryPrefix]);
	}

	szResult.Format(szFormat, dResult);

	return szResult;
}

If you ever find good use of these functions please let me know. I personally use them quite often, hopefully they will be as useful for someone else. Oh, if you wonder how to format a range of bytes this is how to do it:

                DOUBLE dMinSize = 123801, dMaxSize = 92873429;
		BINARYPREFIX ibp = BP_AUTO;
		CString szMaxSize(::FormatBytes(&ibp, dMaxSize, ibp, PN_DECIMAL, 1, TRUE));
		CString szMinSize(::FormatBytes(&ibp, dMinSize, ibp, PN_DECIMAL, 1, FALSE));
		CString szSize;
		szSize.Format(_T("%s-%s"), szMinSize, szMaxSize);
                ...

It is important to note that you might be tempted to do:

                DOUBLE dMinSize = 123801, dMaxSize = 92873429;
                BINARYPREFIX ibp = BP_AUTO;
                CString szSize;
                szSize.Format(_T("%s-%s"),
                                ::FormatBytes(&ibp, dMaxSize, ibp, PN_DECIMAL, 1, TRUE),
                                ::FormatBytes(&ibp, dMinSize, ibp, PN_DECIMAL, 1, FALSE));
                ...

However doing so will most likely result in a wrong output because of the parameter evaluation strategy which might differ from one compiler to another.

Byte Formatting

Now that we know all about the binary prefix origins the next question is how do we format bytes? The answer is not as straightforward as it should be.

This proposed implementation offers 2 options. One is to auto-select the prefix based on the number of bytes and the other is to use a specific prefix. There are two core operations involved in formatting bytes, one is to convert the byte size to the requested unit and the other is to format the converted size into a string, managing decimals.

To help the implementation we need to define a few things. First, will the conversion follow the SI or IEC standard? Then which unit are we making the conversion to? Finally, we need to define the prefixes themselves. To make this all fit together we make the prefix array match the definition of the used norm and the selected unit:

enum PREFIXNORM
{
   PN_SI,                    // Base 10 (i.e. 1000)
   PN_IEC,                   // Base 2 (i.e. 1024)
   PN_DECIMAL = PN_SI,
   PN_BINARY = PN_IEC
};

const INT iPrefixBase[] = { 1000, 1024 };

enum BINARYPREFIX
{
   BP_NONE = -2,
   BP_AUTO,
// SI              IEC 60027      Exp (b10/b2)     Exp (b1000/b1024)
   BP_KILO,        // KIBI        3                1
   BP_MEGA,        // MEBI        6                2
   BP_GIGA,        // GIBI        9                3
   BP_TERA,        // TEBI        12               4
   BP_PETA,        // PEBI        15               5
   BP_EXA,         // EXBI        18               6
   BP_ZETTA,       // ZEBI        21               7
   BP_YOTTA        // YOBI        24               8
};

typedef BINARYPREFIX *LPBINARYPREFIX;

const LPTSTR pszPrefixes[][8] = {
   { _T("KB"),  _T("MB"),  _T("GB"),  _T("TB"),  _T("PB"),  _T("EB"),  _T("ZB"),  _T("YB") },
   { _T("KiB"), _T("MiB"), _T("GiB"), _T("TiB"), _T("PiB"), _T("EiB"), _T("ZiB"), _T("YiB") }
};

To do the actual conversion we need the byte size, the norm to use and the unit to convert to. The function returns the converted byte size and the unit used (if BP_AUTO is specified):

BOOL ConvertBytes(
   ULONGLONG ullSize,
   PREFIXNORM iPrefixNorm,
   BINARYPREFIX iPrefix,
   LPDOUBLE pdResult,
   LPBINARYPREFIX piPrefix)
{
   if (!pdResult || !piPrefix)
       return FALSE;

   DOUBLE dSize = (DOUBLE)ullSize;
   DOUBLE dBase = (FLOAT)iPrefixBase[iPrefixNorm];

   *pdResult = dSize;
   *piPrefix = BP_NONE;

   if (dSize < dBase)    // Already in bytes?
       return TRUE;

   if (iPrefix == BP_AUTO)
       *piPrefix = (BINARYPREFIX)((INT)::floor(::log(dSize) / ::log(dBase)) - 1);
   else
       *piPrefix = iPrefix;

   *pdResult = dSize / ::pow(dBase, (DOUBLE)(*piPrefix) + 1);

   return TRUE;
}

As you may have noticed the auto conversion is flawed. Indeed the maximum precision of a double allows to convert reliably only up to a terabyte. The conversion is still valid with higher values however the auto unit selection will diverge away from the multiple of the base as the number of bytes increases. For example converting the following values:

ULONGLONG ullSizes[] = {
   999ULL,
   1000ULL,                // 1K
   999999ULL,
   1000000ULL,             // 1M
   999999999ULL,
   1000000000ULL,          // 1G
   999999999999ULL,
   1000000000000ULL,       // 1T
   999999999999999ULL,
   1000000000000000ULL,    // 1P
   999999999999999999ULL,
   1000000000000000000ULL, // 1E
   // ...
};

Yields to these results (formatted with %.9f):

999.000000000 B
1.000000000 KB
999.999000000 KB
1.000000000 MB
999.999999000 MB
1.000000000 GB
999.999999999 GB
1.000000000 TB
1.000000000 PB // Should be 999­.999999999 TB but rounded to 1 PB
1.000000000 PB
1.000000000 EB // Should be 999.999999999 PB but rounded to 1 EB
1.000000000 EB

Now formatting the converted size into a readable string is a matter of using the prefix array:

CString FormatBytes(
    ULONGLONG ullBytes,
    INT iDecimals = 3,
    BINARYPREFIX iPrefix = BP_AUTO,
    PREFIXNORM iPrefixNorm = PN_SI)
{
    CString szResult;

    if (iPrefix == BP_NONE)
    {
        szResult.Format(_T("%I64u B"), ullBytes);
    }
    else
    {
        DOUBLE dResult;
        BOOL bRes = ::ConvertBytes(ullBytes, iPrefixNorm, iPrefix, &dResult, &iPrefix);
        ATLASSERT(bRes);

        CString szFormat;
        szFormat.Format(_T("%%.%df %%s"), iDecimals);
        szResult.Format(szFormat, dResult, pszPrefixes[iPrefixNorm][iPrefix]);
    }

    return szResult;
}

Finally, using the formatting is as simple as this:

::_tprintf(_T("%s\n"), ::FormatBytes(357913941));

To give this output:

357.914 MB

The ::MessageBox Case

So lets say you’re popping up a message box in your application like this:

::MessageBox(m_hWnd, _T("Text"), _T("Caption"), MB_ICONINFORMATION | MB_OK);

Fair enough. However there is one problem, where does the window popup?

Well, Windows defaults to popping it up in the center of the default screen. This means if your application window was moved to a corner, or even worst, to another screen and your application happens to pop a message while the focus is on the other screen you’ll get the popup on wrong screen! Talk about confusing a user.

So, whats our solution? Well, Microsoft’s Support KB as an article to provide a workaround in Visual Basic using a Windows CBT hook. You basically create a one time hook to position the window before it appears then remove the hook right away. That works. However, you have to install that hook everytime before calling the MessageBox function.

To ease the process someone on The Code Project also posted an article to streamline the process using C#.

Here’s what it could look like in C++:


class CCenterWindow
{
public:
	CCenterWindow(HWND hWnd)
	{
		m_hWnd = hWnd;
		m_hHook = ::SetWindowsHookEx(
			WH_CBT,
			&CCenterWindow::HookProc,
			(HINSTANCE)::GetWindowLong(m_hWnd, GWL_HINSTANCE),
			::GetCurrentThreadId());
	}

	static LRESULT CALLBACK HookProc(INT nCode, WPARAM wParam, LPARAM lParam)
	{
		if (nCode == HCBT_ACTIVATE)
		{
			RECT r1, r2;
			LONG x, y;
			::GetWindowRect(m_hWnd, &r1);
			::GetWindowRect((HWND)wParam, &r2);
			x = (r1.left + (r1.right - r1.left) / 2) - ((r2.right - r2.left) / 2);
			y = (r1.top + (r1.bottom - r1.top) / 2) - ((r2.bottom - r2.top) / 2);
			::SetWindowPos((HWND)wParam, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
			::UnhookWindowsHookEx(m_hHook);
		}

		return 0;
	}

private:
	static HWND m_hWnd;
	static HHOOK m_hHook;
};

So now you can center a message box by doing this:

CCenterWindow cw(m_hWnd);
::MessageBox(m_hWnd, _T("Text"), _T("Caption"), MB_ICONINFORMATION | MB_OK);

And the hook being installed/uninstalled will do the work of centering the window. Of course, you can compact things even more by creating a macro.

Simulating .NET events in native C++

My last post talks about simulating delegates in native C++ and using them asynchronously. This is all nice, but its far from having all the same features as the equivalent from the CLR. For example, its missing events.

An event is basically like a multicast delegate but it is defined but subscriber objects. An event with no subscribers is basically useless, in fact it will even raise an exception if you call it with no subscriptions.

So as a starter to mimic this behavior in native C++ I created a tiny class to follow my previous design (using IDelegate):

class CEvent
{
public:
	CEvent(BOOL bAutoClean = TRUE) :
		m_bAutoClean(bAutoClean)
	{ }

	virtual ~CEvent()
	{
		if (m_bAutoClean)
			for (INT i = 0; i < m_cDelegates.GetSize(); i++)
				delete m_cDelegates[i];
	}

	VOID operator()(ULONG_PTR ulParam)
	{
		for (INT i = 0; i < m_cDelegates.GetSize(); i++)
 			m_cDelegates[i]->Invoke(ulParam);
	}

	const CEvent &operator+=(IDelegate *pDelegate)
	{
		BOOL bRes = m_cDelegates.Add(pDelegate);
		ATLASSERT(bRes != FALSE);
		return *this;
	}

	const CEvent &operator-=(IDelegate *pDelegate)
	{
		BOOL bRes = m_cDelegates.Remove(pDelegate);
		ATLASSERT(bRes != FALSE);
		return *this;
	}

private:
	BOOL m_bAutoClean;
	CSimpleArray m_cDelegates;
};

As we see there is much resemblance between a delegate and an event as they both can be invoked. In fact, in the CLR an event is a type modifier while a delegate is a reference type meaning events are based on delegates.

So to use the above class you can now do something like this:

class X
{
public:
        CEvent Processed;
        ...
};

class Y
{
public:
        VOID Initialize()
        {
                m_x.Processed += MAKECLSDELEGATE(Y, OnProcessed);
                ...
        }

        ULONG_PTR OnProcessed(ULONG_PTR ulParam)
        {
                ...
                return 0;
        }

private:
        X m_x;
};

I find it pretty neat as it makes code more readable and improves decoupling.

Asynchronous Programming Design Patterns

The .NET Framework includes a lot of asynchronous design patterns such as IAsyncResult and event based asynchronous calls. This is all very nice but unfortunately native C++ programmer are left behind to implement their own solutions for dealing with async calls.

In that line of thought I decided I would implement a piece of the asynchronous patterns in native C++, the IAsyncResult based pattern and since I use WTL to code native Windows applications I adopted the same coding style as WTL.

So here comes my first Code Project article.