2012-03-16 29 views
7

Tôi có một dự án Visual Studio 2008 C++ nơi tôi đang tạo một DLL với giao diện C. Tôi định nghĩa hai loại hàm gọi lại: một hàm thường xuyên và một phần mở rộng cung cấp dữ liệu bổ sung.cắt một lớp xử lý 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); 

Tôi duy trì trạng thái với cấu trúc UserData. Bởi vì tôi có hai loại callbacks, tôi kết thúc với hai cấu trúc:

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

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

Làm thế nào để dung hòa API của tôi với có hai UserData cấu trúc khác nhau mà không cần tạo các phiên bản EX riêng biệt của mỗi chức năng? Có cách nào để templatize gọi lại? Hoặc tạo một lớp cơ sở dữ liệu người dùng?

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

Trả lời

1

Không tao nhã, nhưng nó sẽ làm việc:

  • UserDataUserDataEx của bạn cấu trúc giống hệt nhau ngoại trừ các loại con trỏ. Kết hợp hai cấu trúc đó thành một và thay thế kiểu con trỏ gọi lại bằng FARPROC. Bạn sẽ phải truyền qua lại khi thiết lập và truy xuất các con trỏ hàm đó.
  • Bạn cũng sẽ cần phải thêm một số loại thông tin loại rõ ràng vào cấu trúc của bạn để chỉ định có chuyển kiểu gọi lại sang phiên bản chuẩn hay phiên bản "Ex". Ví dụ: bạn có thể thêm trường flags và đặt cờ USES_EXTENDED_CALLBACK.
+0

Tôi nghĩ đó có thể là những gì tôi sẽ phải làm. Tôi đã hy vọng cho một giải pháp thanh lịch tốt đẹp với các mẫu. Tuy nhiên, đây có thể là giải pháp duy nhất vì bạn không thể thay đổi loại sau khi đối tượng đã được khởi tạo. – PaulH

+0

Lưu ý rằng 'Foo' và' FooEx' đang được truyền bởi * value *. Việc chuyển chúng theo địa chỉ sẽ làm cho việc kết hợp các cuộc gọi lại trở nên dễ dàng hơn. –

+0

@RaymondChen - Khá đúng. Tôi đã cập nhật mã. – PaulH

Các vấn đề liên quan