I have a Visual Studio 2008 C++ project where I'm creating a DLL with a C interface. I defines two types of callback functions: a regular and an extended that provides additional data.
struct Foo {
char a[ MAX_A ];
char b[ MAX_B ];
char c[ MAX_C ];
};
struct FooEx {
char a[ MAX_A ];
char b[ MAX_B ];
char c[ MAX_C ];
char d[ MAX_D ];
};
typedef void ( CALLBACK *USERCALLBACK )( const Foo&, DWORD );
typedef void ( CALLBACK *USERCALLBACK_EX )( const FooEx&, DWORD );
I maintain state with a UserData
structure. Because I have two types of callbacks, I end up with two structures:
struct UserData {
DWORD user;
int zoo;
std::string bar;
USERCALLBACK callback;
};
struct UserDataEx {
DWORD user;
int zoo;
std::string bar;
USERCALLBACK_EX callback;
};
How do I reconcile my API with having two different UserData
structures without creating separate EX versions of every function? Is there a way to templatize the callback? Or create a base-class of user data?
DECLARE_HANDLE( HMYAPI );
// this function is agnostic of the callback type
MY_API HMYAPI MyAPI_Create()
{
return (HMYAPI)new UserData();
}
// This function does not directly use the callback type, but may need to know it to properly deallocate the UserData structure.
MY_API void MyAPI_Close( HMYAPI handle )
{
delete reinterpret_cast< UserData* >( handle );
}
// this function needs to know about the different callback types
MY_API void MyAPI_Register( HMYAPI handle, USERCALLBACK cb, DWORD user )
{
UserData* ud = reinterpret_cast< UserData* >( handle );
ud->cb = cb;
ud->user = user
}
// this function needs to know about the different callback types
MY_API void MyAPI_RegisterEX( HMYAPI handle, USERCALLBACK_EX cb, DWORD user )
{
UserData* ud = reinterpret_cast< UserData* >( handle );
ud->cb = cb;
ud->user = user
}
// this function is agnostic of the callback type
MY_API void Foo( HMYAPI handle, int x )
{
UserData* ud = reinterpret_cast< UserData* >( handle );
ud->bar = "Foo";
ud->zoo = x;
}
Not elegant, but it would work:
UserData
and UserDataEx
structures are identical other than the pointer types. Combine those two structures into one and replace the callback pointer type with FARPROC
. You'd have to cast back and forth when setting and retrieving those function pointers.flags
field and set a USES_EXTENDED_CALLBACK
flag.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With