Once every year or so, I find myself writing/debugging/swearing atC++ code. This year's adventure was brought on by the upgrade ofmy co-dependent application from .NET 1.1 to .NET 2.0 (finally!). It's a
scientific application
that designs genomic assays. It has one particularlycomputation-intensive algorithm that begged for implementation innative code. So, two years ago, I dove into creating a C++application for this purpose.
For those of you who have never crossed the border into C++ Land --
BEWARE
-- C++ gives you enough rope to hang yourself and everyone you haveever said "hello" to. The compilation options alone resemble anApollo spacecraft control panel. Compared to the simple accelerator,brake and steering wheel of VB.NET and C#, it is daunting. After clawing up asteep learning curve with help from people who actually knew what theywere doing and a couple of false starts we developed a workingsolution, which looks something like this...
Though it istheoretically possible to combine Managed C++/Unmanaged C++ in the sameassembly this turned out to be a nightmare, hence the two assembliesinstead of one. The Calculation DLL does the heavy lifting. The Wrapper translates managed communications to the Calculation DLLand returns the results in a managed manner. The VB ControlObject sets up the wrapper and calls it.
Fastforward to this week and our application's move to 2.0. Much likea regular build, I've started by moving the supporting assemblies into2.0 and creating the new versions. Putting off my trip to C++ Land as long as possible, the last two assemblies I move are the Calculation DLL and the Wrapper. Unlike the majority of theVB.NET assemblies, these two, of course didn't just recompile and workin 2.0. That would have been too easy.
I started with the native Calculation DLL, and got a rash of errors that looked like this:
error C2143: syntax error : missing ';' before '<'
HadC++ suddenly changed? Had the conversion fumbled one of the8-gajillion compiler switches? Was there a new compiler switchthat needed to be set? Was there a missing header file? After somegoogling and the requisite swearing, I found the answer. Itturned out to be rather simple. The code in question was usingthe
hash_map
object. Well, that's fine, but it's not in the std namespace, it's inthe stdext namespace. The VS2003 compiler obviously didn't careabout this as much as the VS2005 compiler did. Changing the code inquestion from:
hash_map, double, CHasher> LookupEnergies11;
to
stdext::hash_map, double, CHasher> LookupEnergies11;
fixed the problem, and voila, we had a .NET 2.0 version of this working (well compiled anyway).
On to the Wrapper. It didn't throw any compilation errors, but had 15 linking errors.
LNK2028: unresolved token
This usually means there is something missing, but what? The Wrapperonly relies on the Calculation DLL and the framework."What fresh hellis this?" I thought. Again
Google came to the rescue
.I needed to add the msvcmrt.lib to the Additional Dependencies. I didso and the managed wrapper was compiling and linking! (Thanks toChucker and the mysterious Senthil for documenting the problem and sharing theresolution.)
But what is this new dependency I have just addedto my project? What new bit of magic is now required and for whatreason?
Ah, msvcmrt.lib turns out to be, in
Microsoft's own words
:
The import library references a new library, msvcm80.dll, which provides a proxy between your managed code and the native CRT.
In other words, this is the glue that lets the Managed Wrapper chat with the Native DLL.
So,my annual trip to C++ Land appears to be over. It wasn't as bad as Ihad feared, but I'll be glad to return to a land where the compiler'scommand line doesn't scroll off a 21" monitor.
OK, it's not as as bad as that -- but it's darn close.