visual c++ lesson precompiled headers

I come from a background of managed memory and interpreted languages. I'm a big proponent of pragmatic approaches to problems and as little re-inventing of the wheel as humanly possible. I don't think the world needs another text editor, and I personally don't feel the need to write my own version of the stack I rely on for application development. (.NET Framework and IIS)

This however gives me less credibility with all those "real" programmers out there. The ones who read assembly for fun and don't believe in memory management or virtual runtimes/machines.  I consistently find myself in battles with control freaks who argue that building an application on top of an application server like Tomcat or IIS is dangerous and excessive when it's so much simpler to just write your own daemon and connection handling.

Regardless. It is difficult to argue without having credible experience with the alternatives. Not only that, but a number of my dream jobs require extensive C/C++ knowledge (Google) and many important FOSS projects require the same. So I am finally diving in and (re-)learning some C++ with an initial task of writing an XML to ASN.1 converter. (don't ask why)

I'm doing this in visual studio 2008 with Visual C++, which as I'm learning has it's own learning associated with it. First is the question of ATL , MFC , WIN32  or just Blank. Visual studio doesn't give you a whole lot of background on why you might choose one or the other, but some simple wikipedia reading spelled out that for my project I wanted the simplest option. So I went ahead with Win32 Console as it seemed to have the least amount of overhead with easiest start.

(Why would anyone use the C++ CLR option?)

From here I moved to some very simple HelloWorld love with some file IO. I've taken a course that used C for half of the assignments so I am not completely new to this, but I definitely needed a reminder. Here again I was presented with another option, stdio  or iostream ? More wikipedia love, apparently stdio is the old C way of doing things and iostream is the new object oriented way of doing things. There seems to be a lot of contention still about when to use which when, but for my purposes the stream approach seemed more appropriate.

And include how?

#include "iostream"
#include <iostream>
#include <iostream.h>

Well visual studio doesn't allow the last one so that's easy. Using either of the first two work though works because using the double quotes option will check for an implementation defined location for the file before falling back to the same behavior provided by using the angle brackets. Ok, one more down.

Don't forget that in Visual C++ adding the above import does not explicitly import the associated namespace. So in order to actually use cin or cout you need to either prefix every instance with std::cin or use the statement "using namespace std;" in order to simply use those identifiers normally.

The next couple hours were learning how to create classes, use namespaces and some simple iterative build up of some basic classes to represent the document I needed to import. Still barely outside the realm of a hello world really.

Now, for this little project I am actually more interested in the ASN part of the problem than I am in the XML parsing so I looked for a parser. I came across the autumn project which references a parser written by Dr. Ir. Frank Vanden Berghen which was appealing as it was relatively small, portable and self contained. You can find the files here.

Now for the fun part. When attempting to compile my newly added class was throwing a dozen or so errors that didn't exactly make sense to me. I was prepared for some pretty ugly work in trying to port this thing from GCC to the Microsoft compiler, so I didn't really question these errors. To begin with it was mostly types that were missing. So I would search for the definition of that type and find it in a header file that I was sure was being included. At this point I naively began to move code around in an effort to understand the error. Moving one struct from the header to the cpp file seemed to resolve one error and cause a few more. This seemed to validate my guess that the header was somehow not being included. I had no expectation that this should just work out of the box of course though, so perhaps some of this code was just wrong. I started to chase down the parts of the code that were dependent on flags such as #ifdef WIN32 (I really like how visual studio grays out the code that will not be included based on those conditionals, very nice).

This went on for maybe an hour before I was convinced that this had to be easier. Looking more closely at the build output rather than the error log (which should always be done much sooner than this) revealed this warning :

1>c:\documents and settings\c\my documents\visual studio 2008\projects\xmltoasn\xmltoasn\xmlparser.cpp(82) : warning C4627: '#include <Windows.h>': skipped when looking for precompiled header use
1>        Add directive to 'stdafx.h' or rebuild precompiled header

This is one of those steps where I know I should have asked more questions when I first started my project. The project by default included my "main" file, but it also included these two stdafx files (header and cpp) which I briefly looked at but didn't dig into. The comment at the top of stdafx.h shows this :

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently

Which if you don't know what pre-compiled headers are may not make a ton of sense. And it sounds to me like this is optional in any case. Well, it isn't, at least not if you have the build options on your project set to use precompiled headers which by default I did. Simply adding "#include <windows.h>" to the stdafx.h file resolved all the problems. So in fact the xmlParser module WAS portable, and I just didn't have a clue.

The other way to solve this problem is to actually change the precompiled headers setting for your project to not use precompiled headers at all.

So this was a bit frustrating, but all in all a good first foray into this shit, and I'm at least a few steps closer to having a program that actually does something.