Automation may be a windows only term (it was used when describing the above features for OLE and COM and later frameworks which were windows only).
What I recommend you do is construct a management system that has a registry of all classes and then uses that to do class, function, and data resolution.
Here is a brief outline:
First you create different class types each with their own purpose. They all derive off the base class: each class must return meta-data describing the object type (string and numeric ID) as well as any other simple meta-data you wish to have.
You then provide an interface (which is just a special abstract structure with a pointer to said structure) and then you define specific structures that have a v-table which is just a table of pointers in one column and a meta-data structure in the other column.
The resolution basically resolves the pointer from the meta-data structure.
The quickest way is to use a hash table that is big enough with a good algorithm to minimize collisions and make bin allocation as uniform as possible.
Alternatively you can just loop through all entries until you find what you want.
With those done, you now want to think of how you can create a framework that is easily extendable either through internal addition of functionality or through 3rd party libraries (like DLL's in windows or SO's in linux).
To do this you need to consider what is called a class factory. The class factory basically is given enough information about a class so that it can create it either from a new function (if it's internal) or through a 3rd party interface (if its in a 3rd party library).
The factory manages all objects that have been allocated and you need to include methods to allocate and de-allocate class instances, resolve pointers with named strings, have hierarchical functionality, dependency handling (i.e. if two objects are dependent) and also some kind of event system (like a publish subscribe) that allows external parts of the software to get messages and updates on what is going on.
So when you do this right, you set up the system that it is easily extendable by both 3rd party libraries or by adding internal classes.
This is good when for example you have a custom 3rd party library that implements all your functions.
It's also good for security: what you can do is add a simple trusted/banned functionality at any step of the factory or execution process that does not allow banned classes or classes that it is doesn't know about (in the same a firewall asks you about using a port that it doesn't know about or an application that it doesn't know about) so it can not use it.
It's not only good for security: if you have a 3rd party library that crashes all the time, you can just block it so that it doesn't freeze the rest of the execution going on.
So for resolving your on_click method in a custom internal class or 3rd party library, you just resort to the v_table to get the actual pointer.
The only thing left is known as marshalling: which is a way to prepare the data in one environment for use and execution of in another (again this is a COM term). It simply means that it takes the definition in one and converts it to a format for the new function and environment to use.
So you will need to have a standard way to marshall data. For marshalling what I recommend is that each data-type has its own class (with its own factory and registration) and that you put a simple export and import method in each class that returns a representation of that object in a different format.
I don't recommend you return an actual data structure, but rather a text definition of the object that the class factory uses to create the structure.
The class factory needs this standard function to create a new object given a text definition of the object (like a HTML tag based definition) for some type and returns the object pointer for the proper type if it was successful and returns a NULL pointer if not.
So that's my suggestion: it will require a little bit of time to construct the foundations but the main thing is that it's extensible and doesn't have to be modified much once you create functionality (especially with regards to extensibility) other than if you have other design considerations to make.