
Reece Dunn wrote:
I'm not CORBA expert, but I think it's entirely different beast. To use CORBA object you use stub generated from IDL, how it's related to plugins? While there are some ways to find object dynamically, it's different mechanism from shared libraries, isn't it?
I am not sure how CORBA works. COM generally uses a different mechanism to load COM objects via CoCreateInstance, although DirectX exposes creation functions that circumvent this. I was thinking about being able to use COM/CORBA as a platform for object lifetime and dll lifetime management (as well as things like interface extension, etc.).
I know next to nothing about COM, so can't on this idea. In all cases, I think it's a bit beyond the scope.
I though more about at least some kind of map<string, BasePlugin*> which is updated automatically when you load new DLLs.
So the dll implements some function:
__declspec(dllexport) BasePlugin * GetMyPlugin();
so you can do something like:
void load_plugins( map< string, BasePlugin * > & pi ) { for( map< string, BasePlugin * >::iterator i = pi.begin(); i != pi.end(); ++i ) { boost::dll plugin(( *i ).first ); ( *i ).second = plugin.import< ... >( "GetMyPlugin" ); } }
I haven't said the whole truth ;-) They key of the map is some string name of plugin, which is not related to its library name. The idea is that you can write this: plugin_map<string, Codegen*> codegens; for(unsigned i = 0; i < libraries.size(); ++i) codegens.load(libraries[i]); (where 'libraries' is a vector of libraries filenames). And after that: codegens["i386"]->run(........)
It is possible to keep the DLL in memory until all instances of a class (or set of classes) by incrementing/decrementing a global object count variable on construction/deconstruction as is done when using COM. You then check this variable in the DllCanUnload function.
Yes, I though about it yesterday and decided that some reference counting is needed. It's probably necessary in more ways: dll my_dll("whatever"); plugin_map<string, Codegen*> codegens; codegens.add(my_dll); .... heavy hacking ... my_dll.reload(); It seems that desire to reload all DLL is valid. In this case, you'd need to also update 'codegens' because new version of DLL might have changed the list of exported plugins. So, "dll" class should somehow track all plugin_maps which depend on it. Or emit boost::signal when it's reloaded.
You may need some reference counting mechanism to keep the plugin alive, but this is not necessary if you load all plugins on startup and release them at the end of the run.
This is the simplest approach, but I still thinking about reloading use case. For example, you have GUI application with plugins. You change some of plugins and want the reloaded them without restarting the GUI. Possible? Yes. Critical? Probably not. Can we implement this with little effort?
It should be possible to implement these facilities in a library, e.g.:
class object_counter { private: static int objectCount = 0; public: inline int get_object_count(){ return( objectCount ); } public: inline object_counter(){ ++objectCount; } // make MT aware inline ~object_counter(){ --objectCount; } // make MT aware };
class reference_counter { private: int refCount; public: inline void add_ref(){ ++refCount; } // make MT aware inline void dec_ref() { if( --refCount == 0 ) // make MT aware { delete this; } } public: inline reference_counter( int rc ): refCount( rc ){} inline ~reference_counter(){} };
allowing:
class plugin: public object_counter, public reference_counter, public BasePlugin { // ... };
__declspec(dllexport) BOOL DllCanUnload() { return( object_counter::get_object_count() == 0 ); }
Do you mean that reference counting should be done by DLL itself? Why not: template<class T> class plugin_ptr { public: // operator-> and friends private: T* m_ptr; shared_ptr<dll_handle> m_dll; } So, 'dll' won't be deleted until all plugins which use it are dead. - Volodya