I have a program that loads a bunch of "addons" (different meters that measure and display system values).
The "addons" have "grown" over time and the code of what addons to "activate", and how many of each (if there is more than one of the "device" in the system (cpu's, net-interfaces, etc) is hard-coded into the master. Ug (and ick).
What I want is for each addon-meter to place it's name and init-routine-addr into an array as they are loaded. Right now, what meters that are loaded are fixed in the master at compile time. What I want is for the possibility of dynamic loading, but more importantly, for external "script-extensions" (that could measure "almost anything" and rely on the master to display the collected data (like a script that would read outdoor temperature via some 3rd party device). In other words -- long after the master has been compiled, I want to provide the ability for other addon meters to be added as long as they supply a specific callable API.
Thus, as a new extension is added, I need some init routine to be called as it loads that will place the new meter-name and routine to be called in a class-singleton that has an array of the extension names and their init-routine addresses (as in a dynamically loaded extension).
Then when execution starts, each extension will already have have "registered" itself with a central list that the "master" can look at and know what to call.
In Perl, I've used something in a "BEGIN{...} block" in loaded extensions
to call a Plug_Common->register("plugin name", \%Plugin_Description_Data);
so when the main routine started it would look in the plugin-registry to see
what was available, dynamically, at runtime.
The question is, how do I do this in C++?
I've setup register routine, but I've no idea how to have the extensions get their "name & address" registered before the main-master runs. Theoretically, since some of the extensions could be added via scripts long after the main-master was written -- it wouldn't be able to know their names in advance.
Off the top of my head, I can only think of a "user-edited" static text file, that might be able to have the master, "somehow(?!)" call each extensions init and 'get_config' routine. Then I can get rid of all the 'extension/meter-specific'-knowledge out of the the master. I don't like the text-file idea as it's too prone to user-error -- having something being able to automatically call a register-function as it is loaded, seems much less likely to have problems like the static-config file being out-of-sync with what extensions can be used on the system.
Any ideas? (I'd rather not have to build in a copy of something like Perl to handle the dynamic "loadability" of modules...to me, that would be 'ugly'...
Seem a bit unreliable for the master program to try to look through some symbol table at runtime -- especially with C++'s strong typing. I keep coming up with flaws in virtually every method I think of. :-(. Anyone know a better way? ;-)...
Update:
Had a thought (well more than one, but this one is a bit unconventional, but might work) What if each of the plugins declared a shared pointer to a global list in the master?) If the shared pointers were used in module level inits, then wouldn't the shared 'use count' be incremented as the modules were loaded?...hmmm... I don't know yet how to get the modules' addresses into the main array (without them getting any execution time), but if I can figure out a way for an initializer statement using the shared_ptr, then since loading it a non-multithreaded (at least at this point) if that pointer could be leveraged to increment and store the address of an init function, in a global array, that might give me my dynamic config? Right now, the only thing I know for sure is that shared pointers do have an accessible 'use_count' -- which would only help me in determining how many plugins had registered. Maybe there is no way to make this work, but just a thought (at 5:45am after I've been up all night... so, may be completely flawed and I just don't see it yet...;-))... Anyway, thought I'd add my latest thoughts; For scripts I'm thinking of splitting off that type of plugin into a separate handler that would have to read some config... I don't really like it, but it does isolate those things that wouldn't load @ program start time... Anyone think it is possible to leverage the shared-pointer to do this?