Hello community!
My problem is solved now - thanks jules and all the others!
Now that I finally managed to create my plugin system, I’d like to share some basic thoughts and hints for those, who stumble upon this thread and try to do the same. I will try to use simple words and “pictures” to make it easy to understand. It might not be the best approach, but it works and might help other beginners to get started. Pros will not read anything new…
First of all: Never delete stuff in the library that was allocated in the main application and the other way round. See jules posts above for details. If you need to get data from “the other side”, allocate an array and pass it over. Let the other side fill this array with the data. Then you can safely read the content and then delete it where you created it.
Second: Do not try to pass objects between the library and the main application.
It is possible and it works for some special cases, but sooner or later the problems begin. One big thing is that static classes are not shared between the library and the main application. Thus, everything that relies on anything static will not work. (e.g. any “Component”-derived class will not be repainted - it relies on a static list of top-level components, that is not shared between library and main application).
Overall it is much safer to create a plain and simple C API. Functions that are exported by a dynamic library are well supported and easy to understand. All you need is some kind of abstraction layer that translates calls from C++ objects to simple C function calls and the other way round.
If you’re new to programming concepts, maybe this will help you a bit:
Think of that API as a long pipe that you can shout through. On both ends, you have a crowd of people that want to talk to each other (these are the C++ classes inside the application and inside the library). They can all only shout through this one single pipe. When a sound reaches one end of the pipe, how can you know where it came from an who’s supposed to receive it? Its best to give each person on each side a unique number. So now, when someone from one end wants to talk to someone on the other end of the pipe, he only needs to say his number and the number of the person he would like to talk to. That would work.
But it is not a good solution: Every single person would need to listen to the sound coming out of the pipe - that’s inefficient. It’s much better to have a manager sitting at each end. When someone wants to make a “call”, he lets the manager deliver the message. On the other end, the other manager receives the message and passes it on to its final destination. Thats exactly what you need for a plugin system.
On the application-side:
Write a singleton/static-class for calls to the library and callbacks from the library
[list][]provides static functions that can be passed over to the library as function pointers (done during initialization of the library). These will be used for callbacks from the library to the main application.[/]
[]All C++ objects inside the main application that need to communicate with the library register themselves at this class and a unique ID number is assigned to them[/]
[]C++ objects do calls to this singleton class. It passes these calls on to the library, adding the sender’s ID as well as the ID of the target object as a reference.[/]
[]incoming calls to the callback functions are passed on to their targets, by addressing them via their ID number (which was assigned to them when they registered themselves)[/][/list]
On the library-side:
Export all the functions you need and also provide an init function that takes pointers to all the callbacks. Through these pointers you can call the main application.
Write a singleton-class for calls to the main application and for delivering incoming calls from the application to their target objects
[list][]All C++ objects inside the library, that need to communicate with the main application register there and a unique ID number is assigned to them[/]
[]C++ objects do calls to this singleton class. It passes these calls on to the main application via the callback functions, adding the sender’s ID as well as the ID of the target object as a reference.[/][/list]
In the exported functions of your library, just do a call to this singleton and let it deliver the message to their registered targets.
I hope thats a bit of a help for beginners. Feel free to correct me if anything about that is wrong.
StrangeMan