Sep
25

Into the Abyss: Getting Started with C++ Jon Keon

C++

Background:

Feel free to skip this part if you aren’t interested in why I’m blogging about this and just want the info.

 

First a little bit of background.

I learned Visual Basic, Java and C in Highschool. Those were my first forays into the world of programming and sparked my interest for making things happen on the screen. I did some more Java, C++, OpenGL and finally ActionScript in University. Not to knock the school’s but what I learned was introductory at best. I really became a programmer at my first actual programming job. I was an Actionscript Developer/Designer working on internal tools to help the Support Department more easily get access to information when trying to solve a client’s issue. Not exactly glamorous but it was a great gig while finishing up my degree. That was really where I learned how to program.

Two years later, I had graduated and it was off to an Ad Agency to develop ActionScript based promotional websites and games for pretty much all the big names in advertising. We did the Facebook game thing, we did the Online MMO thing, and even a little game you played via your cellphone up on the Times Square billboards. There it was trial by fire with tight deadlines and radically different challenges for each project. It was there I learned how to architect.

Three years of working my way up through development and then management and I was ready for another change. It’s been just over 4 months now that I’ve been working back as an Actionscript Developer in the tablet and phone space. New challenges and opportunities to be sure but I’ve found myself having less and less unknowns and less challenges to really stimulate that part of the brain that gets excited when you finally figure out just that perfect way to solve the problem at hand.

Don’t get me wrong, I’m not professing to have “Mastered” Actionscript and all there is to learn about Flash Development in the slightest. But I do want to branch out on my own time and start exploring something completely new.

I’ve always been really interested in 3D graphics programming and have been very invested in the new Stage3D technology with Flash Player 11. But if you want the culmination in 3D Graphics, you need to be working with DirectX or OpenGL to get the maximum result.

And so enters C++.

And I mean real C++. I’ve done it before in school, I’ve done some tutorials on the web, even gone through some of the exercises in the Sam’s Teach Yourself C++ in 21 Days. While those were beneficial I found that they don’t convey nearly enough information on actually starting up a project and organizing it in a way to let you build something that’s more than just a quick demo or tutorial. Everything is either in main.cpp or has one or two classes.

What I want is best practices and real-world examples to learn off of. There are a few out there, but mostly it’s a lot of scouring the internet on sites like StackOverflow and the MSDN docs and cross referencing what people are saying with how my gut feels. I feel I’m finally at a point where I can really take off now and start building an application with which to learn from.

I plan on chronicling my journey as it were on this blog so that hopefully others can learn from it, or more likely, those that know better can post in the comments and correct me!

So we’ll see it goes but ultimately I hope to explore as much as I can in the world of C++ and DirectX 11.

Getting Started:

Coming from an ActionScript background, C++ is going to seem complicated and daunting. You get a lot more control, but there’s also quite a few more headaches that you have to deal with.

I’m developing on a Windows 7 x64 using Microsoft Visual Studio 2010 so file paths etc will reflect that.

The first tidbit I learned in wanting to have nice clean organized code was to modify the default templates for new .h and .cpp files.

If you navigate to C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcprojectitems you will find two files.

  • hfile.h
  • newc++file.cpp
These are the files Visual Studio uses when you try and add a new item to your project. By default, these are just empty files but I found myself always copy pasting the same thing, so I modified them to look like this:

 

hfile.h

/*********************************
*Class: CLASSNAME
*Description:
*Author: jkeon
**********************************/

#ifndef _CLASSNAME_H_
#define _CLASSNAME_H_

//////////////////////////////////////////////////////////////////////
// INCLUDES //////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// NAMESPACE /////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

namespace NAMESPACE {

//////////////////////////////////////////////////////////////////////
// GLOBALS ///////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// CLASS DECLARATION /////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

class CLASSNAME {

//PUBLIC FUNCTIONS
public:
CLASSNAME();
CLASSNAME(const CLASSNAME& other);
~CLASSNAME();

//PUBLIC VARIABLES
public:

//PROTECTED FUNCTIONS
protected:

//PROTECTED VARIABLES
protected:

//PRIVATE FUNCTIONS
private:

//PRIVATE VARIABLES
private:

};

//////////////////////////////////////////////////////////////////////
// STATICS ///////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

}
#endif

 

 newc++file.cpp

//////////////////////////////////////////////////////////////////////
// INCLUDES //////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// NAMESPACE /////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

namespace NAMESPACE {

//////////////////////////////////////////////////////////////////////
// STATICS ///////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// CONSTRUCTORS //////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

CLASSNAME::CLASSNAME() {

}

CLASSNAME::CLASSNAME(const CLASSNAME& other) {

}

//////////////////////////////////////////////////////////////////////
// DESTRUCTOR ////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

CLASSNAME::~CLASSNAME() {

}

//////////////////////////////////////////////////////////////////////
// INITIALIZE ////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// DESTROY ///////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// BODY //////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// GETTERS/SETTERS ///////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

}
Simple, and easy. Takes care of my header blockers, Constructor, Copy Constructor, Destructor and nice neat subsections for organizing my code. Of course most of the time a class won’t use all of it, but it’s way easier to delete than copy paste everytime I want  to use it.

 

The one thing to note is that this is just straight text, there’s no automatic replacement happening based on class name or anything like that. You still have to manually replace those with the class and namespace names you chose.

Organization:

The next bit to tackle was class organization. Being from an Actionscript background, my classes have always been organized into packages which are reflected on the file system and broken down into sub sections denoting functionality. In C++ this doesn’t have to be the case. The majority of the tutorials out there just put every single file into the same directory because it’s easy to do include statements.

 

In my research I haven’t found a consistent best practice for this, even looking at some prominent 3D engines out there like Wild Magic 5 and Ogre3D they vary pretty significantly. WildMagic has a few main folders and some sub folders but the .cpp and .h files are kept together. Ogre3D has a src and include directory and keeps all the cpp files in the src directory and all the h files in the include directory.

 

The lack of enforcement really means you can do anything that works for your workflow and team unlike languages like ActionScript or Java where classes must be named as they are on the file system and located in nested folder structures that reflect their package location.

 

In Visual Studio there is the concept of filters in the solution explorer. These filters would allow you to organize your files nicely regardless of what the representation is on the file system.

 

Personally, the rules I’m going to use are that classes must be named as they are defined. If the class is called DebugUtil.h, the classname is DebugUtil. As well the organization of the Solution Explorer filters will mimic the file system exactly. It’s close to the packages I’m used to and I think it makes thing readable.

 

Here’s my current Solution Explorer:

 

 

I’m keeping my headers and cpp files together as well.

 

Now the only issue this brings up is the include statements so you just need to edit your include directories to include the root of your project’s source tree.

 

 

Right where it says “Additional Include Directories” I’ve added “..\” and the path to my src directory in my project. “C:\__WORK\DX11\Athena\trunk\Athena\Athena\src”

 

Now when I do Include statements they’re simply the fully qualified path on the file system relative to my src directory.

 

ex. #include <util/DebugUtil.h>

 

I’ll confess that I’m not 100% sure what’s going on here. Before doing this step, I would simply do #include “DebugUtil.h” because that was what intellisense was giving me. However when I would come back the next day, it would error and be unable to find the file. The intellisense and error checking seems flaky at best though with Visual Studio which is surprising. But I guess that I’m just used to the awesomeness that is FDT.

 

Strings:

Strings are annoying in C++. Really annoying. It’s not a native type, and any string classes that exist essentially just wrap an array of characters. Which is fine, except that there are different Type’s of characters depending on your encoding. I’m not going to get into it, a quick google search will show you what I mean. Ultimately though it seems as though you want to use TCHAR which automatically decides to use char or wchar_t depending if you’re using ANSI or UNICODE character encoding.

 

Problem is there’s no TSTRING, just std::string and std::wstring.

 

So I’ve just created a class called TString.h which uses the magic of typedefs to declare my own type called tstring which is a basic_string vector of TCHARS. If you look at the definition of string and wstring you’ll find they are just basic_string vectors of chars and wchar_t’s respectively.

 

C++ and the Windows library especially is littered with these typedefs so it’s imperative to look these up so you can see what you are really dealing with and how to cast between them.

 

The good thing about using tstring everywhere is that in the event I change over to some other kind of string, I can simply update the typedef and barring and API changes, the rest of my code still works.

 

TString.h

/*********************************
*Class: TSTRING
*Description:
*Author: jkeon
**********************************/

#ifndef _TSTRING_H_
#define _TSTRING_H_

//////////////////////////////////////////////////////////////////////
// INCLUDES //////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

#include &lt;string&gt;
#include &lt;tchar.h&gt;

//////////////////////////////////////////////////////////////////////
// TYPEDEF ///////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

typedef std::basic_string&lt;TCHAR&gt; tstring;

#endif

Debugging in a Windows Application:

 

The final part of this Getting Started in outputting Debug Statements to the console when running a Windows application.

 

The famous printf or cout will output to the console if you’re writing a Console application (window with the black DOS like background and white text) but if you’re writing a Windows application, you don’t get a black console window by default. You can enable it if you like but there is also a handy function called OutputDebugString which will write out to the console in Visual Studio.

 

Only problem is that it doesn’t take in variable arguments so you can print values of ints or strings etc. You’d have to process that, put it in a compatible string with a LPCWSTR which is a Long Pointer to a Wide Character String and then send it to the OutputDebugString function.

 

If you’re doing serious debugging you should be using the debugger and stepping through, but sometimes you just want quick easy traces that you can monitor the console window more without halting execution of your program. Doing all those steps would make it tedious and annoying.

 

So I created a class called DebugUtil which will handle those things for me.

 

DebugUtil.h

/*********************************
*Class: DebugUtil
*Description:
*Author: jkeon
**********************************/

#ifndef _DEBUGUTIL_H_
#define _DEBUGUTIL_H_

#ifdef NDEBUG
#define dtrace(message, ...)
#define etrace(message, ...)
#define itrace(message, ...)
#else
#define __FILE_W__ TEXT(__FILE__)
#define __FUNCTION_W__ TEXT(__FUNCTION__)
#define dtrace(message, ...) \
DebugUtil::outputDebugTrace(TEXT("DEBUG"), __FILE_W__, __FUNCTION_W__, __LINE__, TEXT(message), ##__VA_ARGS__)
#define etrace(message, ...) \
DebugUtil::outputDebugTrace(TEXT("ERROR"), __FILE_W__, __FUNCTION_W__, __LINE__, TEXT(message), ##__VA_ARGS__)
#define itrace(message, ...) \
DebugUtil::outputDebugTrace(TEXT("INFO"), __FILE_W__, __FUNCTION_W__, __LINE__, TEXT(message), ##__VA_ARGS__)
#endif

//////////////////////////////////////////////////////////////////////
// INCLUDES //////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

#include &lt;Windows.h&gt;
#include &lt;string/TString.h&gt;
#include &lt;sstream&gt;

//////////////////////////////////////////////////////////////////////
// NAMESPACE /////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

namespace Athena {

//////////////////////////////////////////////////////////////////////
// CLASS DECLARATION /////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

class DebugUtil {

//PUBLIC FUNCTIONS
public:
static void outputDebugTrace(const TCHAR* type, const TCHAR* file, const TCHAR* function, const unsigned long line, const TCHAR* message, ...);

//PUBLIC VARIABLES
public:

//PROTECTED FUNCTIONS
protected:

//PROTECTED VARIABLES
protected:

//PRIVATE FUNCTIONS
private:

//PRIVATE VARIABLES
private:

};

//////////////////////////////////////////////////////////////////////
// STATICS ///////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

}
#endif
The main purpose of this Header is to allow you to do a one line call via a macro.

 

I have three defined if and only if we are in Debug mode. In Release mode these macros won’t do anything because the macro NDEBUG only exists in Release mode.

 

There there are the macro’s __FILE__ and __FUNCTION__ which return the file name and path and the function name respectively. I should probably update this to handle it in TCHAR way but for now I’m forcing them to be Wide Characters since I know I’m working in UNICODE mode.

 

dtrace, etrace and itrace stand for debug trace, error trace and info trace respectively and they simply take in a message as and a variable amount of arguments as if it were a printf statement.

 

Which means you’ll need to know the codes for the different variables you pass in. You can find a good listing of them here.

 

This macro simply calls the Static function defined in DebugUtil.h and handles passing in the type, filename, function and line number for you.

 

DebugUtil.cpp is where the function gets implemented.

 

DebugUtil.cpp

//////////////////////////////////////////////////////////////////////
// INCLUDES //////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

#include "DebugUtil.h"

//////////////////////////////////////////////////////////////////////
// NAMESPACE /////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

namespace Athena {

//////////////////////////////////////////////////////////////////////
// STATICS ///////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

void DebugUtil::outputDebugTrace(const TCHAR* type, const TCHAR* file, const TCHAR* function, const unsigned long line, const TCHAR* message, ...) {

tstring formattedFile;
formattedFile.append(file);

size_t index;
index = formattedFile.find_last_of('\\');

tstring output;
output.append(type);
output.append(TEXT(" ["));
output.append(formattedFile.substr(index+1));
output.append(TEXT(" :: "));
output.append(function);
output.append(TEXT(" : "));

std::wostringstream oss;
oss &lt;&lt; line;
output.append(oss.str());

output.append(TEXT("] - "));

va_list argptr;
int len;
va_start(argptr, message);
len = _vsctprintf(message, argptr) + 1;
TCHAR* userOutput = new TCHAR[len];
_vstprintf(userOutput, message, argptr);
output.append(userOutput);
delete userOutput;

output.append(TEXT("\n"));

OutputDebugString(output.c_str());

}

}
The first thing to notice is that although the Header file has static void as the declaration, the cpp file does not. Confused me for quite some time as I was getting errors until I dropped the static in the cpp file. I can only guess that the declaration says it’s static and the implementation is just a method on the Class DebugUtil and doesn’t need another static keyword.

 

Inside I do some String formatting on the file since I just want the name and not the whole path. Then I construct the output string into a temp tstring. For the line number I have to use the stringstream in order to convert from int to String. finally there are the arguments. Since it’s a variable number of arguments and I don’t know how many there are or what types there are, (And there is very little support for Run Time Type Checking) we use some interesting functions.

 

First is va_list which declared that we need a pointer to a list of arguments. We use va_start to point to the last known argument that came in from a function which in our case is message. Then the function _vsctprintf looks at the message and the variables passed in and returns the length of how long a string would need to be to hold all the information we passed in plus the expanded variables.

 

Next we create a new TCHAR array of that same length and use the _vstprintf function to essentially do a printf into that TCHAR array. It handles all the variable substitution so we don’t have to.

 

We can then append it to our output string and delete that temporary TCHAR array. This is very important so we don’t have memory leaks.

 

Finally we can send the whole thing to OutputDebugString and get a nicely formatted message in return.

 

So when we call:

 

dtrace("This is a Debug Trace with string %s and int %d and character %c!", TEXT("Test"), 48, 'y');

 

We get:

 

 

This gives me a nice way to easily see that I wanted to debug some values in main.cpp in the WinMain function at line 29.

 

Now we’re ready to actual start making something appear on the screen!

 

But that’s for next time.

This entry was posted on Sunday, September 25th, 2011 at 10:13 pm and is filed under C++. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.