To add a new function to the cute Interface, follow these steps:
To add a new function to the cute Interface, follow these steps:
1. Declare the function in cute.h with `DYNAMIC`.
1. Declare the function in cute.h with `DYNAMIC`.
```
```cpp
void DYNAMIC setPlotTheme(int themeNumber);
void DYNAMIC setPlotTheme(int themeNumber);
```
```
2. Define the function in cute.cpp. Most likely you just funnel the call and it's parameters into the `CuteControl`-Singleton, to then be able to use Qt's signals and slots.
2. Define the function in cute.cpp. Most likely you just funnel the call and it's parameters into the `CuteControl`-Singleton, to then be able to use Qt's signals and slots.
```
```cpp
void cute::setPlotTheme(int themeNumber)
void cute::setPlotTheme(int themeNumber)
{
{
CuteControl::get().setPlotTheme(themeNumber);
CuteControl::get().setPlotTheme(themeNumber);
}
}
```
```
3. Define a `signal` in CuteControl, corresponding to your function. To avoid naming conflicts, I used the prefix `s_` in CuteControl. `signals` are always void functions, they are defined by the Qt Meta Object Compiler during the compilation. Think of them as part of the Observer-Pattern, they send a `signal` to all connected `slots`.
3. Define a `signal` in CuteControl, corresponding to your function. To avoid naming conflicts, I used the prefix `s_` in CuteControl. `signals` are always void functions, they are defined by the Qt Meta Object Compiler during the compilation. Think of them as part of the Observer-Pattern, they send a `signal` to all connected `slots`.
```
```cpp
void s_setPlotTheme(int);
void s_setPlotTheme(int);
```
```
4. Declare and define the member function publically in CuteControl. Since Qt's built in types, like `QString` don't require extra steps to be able use them in `signals`, it is advisable to any conversions here. Then `emit` a your `signal`, which will carry the necessary information over the thread boundary. `emit` may be thought of as `fireX()` in the Observer-Pattern.
4. Declare and define the member function publically in CuteControl. Since Qt's built in types, like `QString` don't require extra steps to be able use them in `signals`, it is advisable to any conversions here. Then `emit` a your `signal`, which will carry the necessary information over the thread boundary. `emit` may be thought of as `fireX()` in the Observer-Pattern.
```
```cpp
void setChartTheme(int themeNumber)
void setChartTheme(int themeNumber)
{
{
emit s_setPlotTheme(themeNumber);
emit s_setPlotTheme(themeNumber);
}
}
```
```
5. Now define the fitting `slot` in `control.h`, which will be used to receive your `signal`. In the Observer-Pattern, this is the listener function. Technically it only needs to be `public`, if you want to connect to or call it from another class.
5. Now define the fitting `slot` in `control.h`, which will be used to receive your `signal`. In the Observer-Pattern, this is the listener function. Technically it only needs to be `public`, if you want to connect to or call it from another class.
```
```cpp
public slots:
public slots:
void setPlotTheme(int themeNumber);
void setPlotTheme(int themeNumber);
```
```
6. Now define the `slot` like a regular function in `control.cpp`. Here is *finally*, where you implementation should be placed. The View lives in the `MainWindow` member `_w`. In this case, I call a member function of the View.
6. Now define the `slot` like a regular function in `control.cpp`. Here is *finally*, where you implementation should be placed. The View lives in the `MainWindow` member `_w`. In this case, I call a member function of the View.
```
```cpp
void Control::setPlotTheme(int themeNumber)
void Control::setPlotTheme(int themeNumber)
{
{
_w->changeChartTheme(themeNumber);
_w->changeChartTheme(themeNumber);
}
}
```
```
7. Lastly, connect `signal` and `slot` in `makeConnections()` of the `Control`. This completes the Observer-Pattern, by subscribing `Control` to `CuteControl`.
7. Lastly, connect `signal` and `slot` in `makeConnections()` of the `Control`. This completes the Observer-Pattern, by subscribing `Control` to `CuteControl`.
Connections are pretty resilient. They check if the listener still exists, as well as in which thread they are. If the listener is in another thread, the `signal` will be queued in the threads corresponding event queue.
Connections are pretty resilient. They check if the listener still exists, as well as in which thread they are. If the listener is in another thread, the `signal` will be queued in the threads corresponding event queue.
With clang, this command has to be quite verbose, the basic pattern is: `Sender, &signal, Receiver, &slot`
With clang, this command has to be quite verbose, the basic pattern is: `Sender, &signal, Receiver, &slot`
8. Almost forgot: Of course add some Doxygen. At least in `cute.h`.
8. Almost forgot: Of course add some Doxygen. At least in `cute.h`.
9. Build.
Up to here it works when using the compiled import library `libcute.dll.a`. If you want to be able to load the dll at runtime, continue.
# TODO
10. The linker exports a `cute.def` file in the build directory. In this file, search the mangled function name. It contains the function name and it's namespace, so you can use Ctrl+F to find it.
## without importlib
Copy this string and paste it into the `cute.def` file in the source directory. Here, create an alias with the plain function name.
This way, the `cuteImporter.cpp` is simpler to read. It is also possible to use the mangled name there.
```cpp
setPlotTheme=_ZN4cute12setPlotThemeEi
setPlotTheme=_ZN4cute12setPlotThemeEi
```
11. Now, in `cuteImporter.cpp` do the following:
1. In the anonymous namespace, create a `typedef` for an appropriate function pointer to your function.
```cpp
typedef void (*t_setPlotTheme)(int);
```
2. Create an empty function pointer .
```cpp
t_setPlotTheme setPlotThemeImpl = nullptr;
```
3. Populate the function pointer by retreiving the Address inside the dynamic library and casting it to the type defined above. Here the alias from `cute.def` is used.
4. Check if you got a pointer by adding it to the if-condition with a logical boolean operator `&&`.
```cpp
if(
// ...
setPlotThemeImpl &&
// ...
)
```
5. Define the function you declared in `cute.h`. This definition calls the populated function pointer and returns it's result. Since it has been checked beforehand, another check can be neglected here for our purposes.
```cpp
void setPlotTheme(int themeNumber)
{
return setPlotThemeImpl(themeNumber);
}
```
6. Lastly, in `shutdown()` clear the function pointer again. This should not be critical, since the function is only called when the process exits anyway.
```cpp
setPlotThemeImpl = nullptr;
```
12. Done! Now test if it works with the appropriate example. :D