OK, I have sort of a tricky problem I'm attempting to solve. First of all, an overview:
I have an external API not under my control, which is used by a massive amount of legacy code.
- There are several classes of bugs in the legacy code that could potentially be detected at run-time, if only the external API was written to track its own usage, but it is not.
- I need to find a solution that would allow me to redirect calls to the external API into a tracking framework that would track api usage and log errors.
- Ideally, I would like the log to reflect the file and line number of the API call that triggered the error, if possible.
Here is an example of a class of errors that I would like to track. The API we use has two functions. I'll call them GetAmount, and SetAmount. They look something like this:
// Get an indexed amount
long GetAmount(short Idx);
// Set an indexed amount
void SetAmount(short Idx, long amount);
These are regular C functions. One bug I am trying to detect at runtime is when GetAmount is called with an Idx that hasn't already been set with SetAmount.
Now, all of the API calls are contained within a namespace (call it api_ns), however they weren't always in the past. So, of course the legacy code just threw a "using namespace api_ns;" in their stdafx.h file and called it good.
My first attempt was to use the preprocessor to redirect API calls to my own tracking framework. It looked something like this:
// in FormTrackingFramework.h
class FormTrackingFramework
{
private:
static FormTrackingFramework* current;
public:
static FormTrackingFramework* GetCurrent();
long GetAmount(short Idx, const std::string& file, size_t line)
{
// track usage, log errors as needed
api_ns::GetAmount(Idx);
}
};
#define GetAmount(Idx) (FormTrackingFramework::GetCurrent()->GetAmount(Idx, __FILE__, __LINE__))
Then, in stdafx.h:
// in stdafx.h
#include "theAPI.h"
#include "FormTrackingFramework.h"
#include "LegacyPCHIncludes.h"
Now, this works fine for GetAmount and SetAmount, but there's a problem. The API also has a SetString(short Idx, const char* str). At some point, our legacy code added an overload: SetString(short Idx, const std::string& str) for convenience. The problem is, the preprocessor doesn't know or care whether you are calling SetString or defining a SetString overload. It just sees "SetString" and replaces it with the macro definition. Which of course doesn't compile when defining a new SetString overload.
I could potentially reorder the #includes in stdafx.h to include FormTrackingFramework.h after LegacyPCHIncludes.h, however that would mean that none of the code in the LegacyPCHIncludes.h include tree would be tracked.
So I guess I have two questions at this point: 1: how do I solve the API overload problem? 2: Is there some other method of doing what I want to do that works better?
Note: I am using Visual Studio 2008 w/SP1.