2012-03-16 6 views
7

Tengo un proyecto de Visual Studio 2008 C++ donde estoy creando una DLL con una interfaz C. Defino dos tipos de funciones de devolución de llamada: una regular y una extendida que proporciona datos adicionales.cortar una clase de control DLL

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); 

que mantienen el estado con una estructura UserData. Porque tengo dos tipos de devoluciones de llamada, que terminan con dos estructuras:

struct UserData { 
    DWORD user; 
    int zoo; 
    std::string bar; 
    USERCALLBACK callback; 
}; 

struct UserDataEx { 
    DWORD user; 
    int zoo; 
    std::string bar; 
    USERCALLBACK_EX callback; 
}; 

¿Cómo conciliar mi API con tener dos estructuras diferentes UserData sin crear versiones EX separadas de cada función? ¿Hay alguna manera de templatar la devolución de llamada? ¿O crear una clase base de datos de usuario?

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; 
} 
+11

http://www.partow.net/programming/templatecallback/index.html#VariableArgumentDerivative – Flot2011

Respuesta

1

No es elegante, pero funcionaría:

  • Sus UserData y UserDataEx estructuras son otra idéntica que los tipos de puntero. Combine esas dos estructuras en una y reemplace el tipo de puntero de devolución de llamada con FARPROC. Tendría que lanzar hacia adelante y hacia atrás al configurar y recuperar esos punteros de función.
  • También necesitaría agregar algún tipo de información de tipo explícito a su estructura para especificar si desea convertir la devolución de llamada a la versión estándar o la versión "Ex". Por ejemplo, puede agregar un campo flags y establecer un indicador USES_EXTENDED_CALLBACK.
+0

Creo que eso es probablemente lo que tendré que hacer. Esperaba una buena solución elegante con plantillas. Sin embargo, esta puede ser la única solución ya que no puede cambiar el tipo después de que el objeto ha sido instanciado. – PaulH

+0

Tenga en cuenta que 'Foo' y' FooEx' se pasan por * valor *. Al pasarlos por la dirección, será más fácil fusionar las devoluciones de llamada. –

+0

@RaymondChen - Muy bien. He actualizado el código. – PaulH

Cuestiones relacionadas