2011-01-26 23 views
5

Tôi đang tìm cách triển khai kiến ​​trúc plugin vào ứng dụng hiện tại của chúng tôi (Unix, C++) và đã xem xét các tùy chọn (đang chờ phê duyệt) trong thư viện Boost.Tăng các lựa chọn Plugin

Chỉnh sửa: Tôi đang tìm kiếm để tự động thêm lớp học vào thời gian chạy.

Boost.Plugin

Boost.Reflection

Boost.Extension

tôi đã tự hỏi những gì everyones kinh nghiệm/ý kiến ​​là trên những điều này và khác triển khai.

+1

Bạn đã đăng các giải pháp được đề xuất cho một vấn đề mà bạn không nêu. Yêu cầu của bạn là gì? –

Trả lời

4

Eh. Chúng tôi chỉ sử dụng dlopendlsym cùng với một cặp extern "C" static chức năng mà phải được xác định trong dll

extern "C" static plugin* create(arg_pack*); 
extern "C" static errno_t destroy(plugin*); 

Có một cái nhìn plugin quản lý cho ".dll" hoặc ".so" tập tin và tải chúng vào một
map<string, pair< plugin*(*)(arg_pack*), errno_t(*)(plugin*)> >

Bạn có thể sau đó tra cứu một plugin dựa trên một tên (chuỗi ở trên) và làm cho nó là 'constructor' hoặc 'destructor'

xem thêm: gmodule

+0

Kiểm tra khả năng tương thích ABI/API? –

+0

@Vlad ABI -> 'extern" C "' đảm bảo x-style mangling. API -> 'dlsym' để tải tất cả các hàm có liên quan từ thư viện. Nếu bất kỳ bị thiếu thì nó không phải là một plugin và bạn cần phải loại bỏ các con trỏ hàm và 'dlclose' thư viện. – KitsuneYMG

+1

extern "C" đảm bảo mangling, nhưng hãy tưởng tượng rằng chữ ký đã thay đổi, hoặc bất kỳ giao diện host nào đã thay đổi, và plugin mong đợi điều khác nhau, đặt cược tốt nhất sẽ sụp đổ, nhưng hậu quả có thể rất ấn tượng (tức là giá xấu đến từ giao dịch hệ thống, khiến một công ty bị phá sản trong vài giây). Nên có một bộ kiểm tra phong nha đảm bảo rằng bất kỳ hợp đồng nào được kỳ vọng sẽ được đáp ứng. Điều này về cơ bản nên là một mục tiêu chính của khuôn khổ plugin, không chỉ gói dlopen ... –

1

Bạn không thể tải các lớp tại thời gian chạy vì C++ là một ngôn ngữ và các lớp được biên dịch không tồn tại trong thời gian chạy. Các đối tượng (các thể hiện của các lớp) làm.

Việc bạn có thể làm là tải các thư viện được chia sẻ vào thời gian chạy và làm cho chúng tạo các đối tượng của một giao diện nhất định.

Triển khai trình cắm thêm tối thiểu sẽ xác định giao diện của trình cắm của bạn và giao diện của chức năng nhà máy sẽ tạo đối tượng với giao diện đó. Bạn sẽ tải thư viện được chia sẻ vào thời gian chạy, tìm hàm nhà máy với một tên nhất định và gọi hàm nhà máy để tạo một đối tượng. Sau đó, bạn sử dụng đối tượng đó mặc dù giao diện:

// plugin.h start 
#include <memory> 

struct PlugIn // interface 
{ 
    virtual ~PlugIn() = 0; 
    virtual void doSomething() = 0; 
}; 

extern "C" { 

typedef std::auto_ptr<PlugIn> PlugInFactoryFn(); 

// A plugin .so must export this one factory function. 
std::auto_ptr<PlugIn> createPlugIn(); 

} 
// plugin.h end 

// somewhere in you application 
#include "plugin.h" 
#include <assert.h> 
#include <dlfcn.h> 

std::auto_ptr<PlugIn> loadPlugIn(char const* filename) 
{ 
    void* so = dlopen(filename, RTLD_NOW | RTLD_LOCAL); 
    assert(so); 
    void* factory_function = dlsym(so, "createPlugIn"); 
    assert(factory_function); 
    return reinterpret_cast<PlugInFactoryFn*>(factory_function)(); 
} 

int main() 
{ 
    std::auto_ptr<PlugIn> a(loadPlugIn("a.so")); 
    std::auto_ptr<PlugIn> b(loadPlugIn("b.so")); 
    a->doSomething(); 
    b->doSomething(); 
} 
+0

Bây giờ, điều này sẽ không hoạt động trên nền tảng không POSIX, có thể có vấn đề heap khi đối tượng được phân bổ trên đống của plugin và bị xóa trong các ứng dụng chính. Chưa kể đến khả năng tương thích API/ABI ... –

+0

@Vlad: chúng ta đang nói về Unix ở đây. –

+0

@Maxim: Tuy nhiên, bạn phải đảm bảo rằng plugin và máy chủ có khả năng tương thích ABI (tức là trình biên dịch tương tự hoặc tương thích, vv), cộng với API tương thích. Đó là lý do tại sao bạn cần một số công cụ cấp cao hơn như Tăng cường và sử dụng dlopen cao bồi là .. bạn biết đấy. –

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