Welcome to MSDN Blogs Sign in | Join | Help

The Case of the Unexpected Overload

So are you using C++ in a KMDF driver and scratching your head over some unexpectedly unresolved references?

I recently engaged in a somewhat prolonged conversation with Doron and a dev I won’t name [since I didn’t ask for permission] about C++ in KMDF driver.  This dev (a very good dev, by the way) had hit a stumbling point converting a driver from C to C++ and was wondering if we had ever tried this in QA.

Yes, I know that means he/she doesn’t read this blog, since I’ve mentioned doing just that on more than one occasion.  But that’s OK, not many people do- and since I’ve got a tendency to write about whatever strikes my fancy at any moment, and I’m not the most dazzlingly brilliant human on the face of the planet, that’s not much of a surprise to me.  You are of course free to believe what you like about that statement.

But in an attempt to be useful today- the problem was one of those that I guess I’ve hit so many times I don’t give it much thought.  But it gave our dev a bit of trouble, and not much gives this person that kind of trouble.  So perhaps a word to the wise will give the three or four of you still reading this a leg up the next time you use C++ in a KMDF driver.

The Lesson for Today Is…

It was just a simple conversion of a driver from C to C++ (to gauge my familiarity with the process, I did that with a half dozen or more drivers last week, and it was far from the only thing I did that week- in fact the big job was actually that I also made them W4 and PFD clean along with quite a few more drivers I’d already converted to C++- almost two dozen drivers total), but it ran afoul of this little bit of goodness:

typedef
__drv_functionClass(EVT_WDF_OBJECT_CONTEXT_CLEANUP)
__drv_sameIRQL
__drv_maxIRQL(DISPATCH_LEVEL)
VOID
EVT_WDF_OBJECT_CONTEXT_CLEANUP(
    __in
    WDFOBJECT Object
    );

typedef EVT_WDF_OBJECT_CONTEXT_CLEANUP *PFN_WDF_OBJECT_CONTEXT_CLEANUP;

That’s the “role typedef” for any WDF object’s context cleanup routine.  The SDV tool can use role typedefs to do a better job of statically verifying your driver code, so some special cleanup typedefs are defined to make it a better tool, and you can see them in this (by the way, everything I’m posting is from the WDK- no deep dark secrets here).

typedef EVT_WDF_OBJECT_CONTEXT_CLEANUP EVT_WDF_DEVICE_CONTEXT_CLEANUP;
typedef EVT_WDF_OBJECT_CONTEXT_DESTROY EVT_WDF_DEVICE_CONTEXT_DESTROY;
typedef EVT_WDF_OBJECT_CONTEXT_CLEANUP EVT_WDF_IO_QUEUE_CONTEXT_CLEANUP_CALLBACK;
typedef EVT_WDF_OBJECT_CONTEXT_DESTROY EVT_WDF_IO_QUEUE_CONTEXT_DESTROY_CALLBACK;
typedef EVT_WDF_OBJECT_CONTEXT_CLEANUP EVT_WDF_FILE_CONTEXT_CLEANUP_CALLBACK;
typedef EVT_WDF_OBJECT_CONTEXT_DESTROY EVT_WDF_FILE_CONTEXT_DESTROY_CALLBACK;

So, what the original driver, being a good sample [because SDV suitability also matters], had was something like this (not exactly like this- nobody with my twisted sense of humor writes sample code, because humor never works globally- someone always takes offense- I’m just not inclined to care about that anymore, because I’m a callous old bastard with less than a dozen years to retirement age and not much “career” left to lose):

// In the header file:

EVT_WDF_DEVICE_CONTEXT_CLEANUP HideTheBodies;

// In the implementation
VOID
HideTheBodies(
    __in WDFDEVICE MortTheMortuaryTechnicianIsOnTheJob
    )
{
...

Of course, in C, that sort of works- but in C++, that says you have two overloaded versions of HideTheBodies- one takes a WDFOBJECT as input, and isn’t defined, because nobody wrote it that way.  The one that is defined takes a WDFDEVICE as input.  More annoying, of course, is that from the typedef name, you’d expect it would take a WDFDEVICE as input, so it isn’t an error that’s glaringly obvious.

As is- the code will compile fine, and PFD will be happy, too [they’re not the same function, remember].  But when you link it, you get an unresolved reference for HideTheBodies- decorated to indicate it has a WDFOBJECT parameter.  Now, unless you really look closely at such decorations (something my fine history of mistyping the simplest of code has taught me to do), you’re looking at a mystery.  It took my colleague digging through preprocessor output and object files and such to finally hit upon the error- a reasonably annoying circumstance!

Another thing you can do (and this is what I usually do) is tie the callbacks to the context itself (with the context a class) as static member functions, as I described earlier (effectively you do the cleanup by calling the context’s “delete” operator).  PFD currently doesn’t match the roletype if you do this, so I suppress those warnings (and there is no SDV for C++)- I think we’re trying to get that fixed…  But the compiler will catch the parameter type mismatch- a bit earlier than the linker.

But I’ve hosed this both ways- so, until something on the subject gets posted by a recognized authority, this post can at least be found by the diligent searcher…

Published Monday, August 03, 2009 7:31 AM by BobKjelgaard
Filed under: , , ,

Comments

No Comments
New Comments to this post are disabled
 
Page view tracker