Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

slicing a DLL handle class

Tags:

c++

dll

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;
}
like image 947
PaulH Avatar asked Mar 16 '12 20:03

PaulH


1 Answers

Not elegant, but it would work:

  • Your 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.
  • You'd also need to add some kind of explicit type information to your structure to specify whether to cast the callback to the standard version or the "Ex" version. For example, you could add a flags field and set a USES_EXTENDED_CALLBACK flag.
like image 82
Aaron Klotz Avatar answered Oct 01 '22 18:10

Aaron Klotz