1

I have a Qt-based project that loads plugins via QPluginLoader.

These plugins inherit class Plugin from this project.

Plugin.h

#ifndef PLUGIN_H
#define PLUGIN_H
class Plugin:public QObject
{
public:
    inline static MyObj* obj;
};
Q_DECLARE_INTERFACE(Plugin,Plugin_iid)
#endif

I need to be able to access static pointer 'obj' from all plugins, which is initialized before any plugins are loaded.

The problem is that if I try to access the pointer from a plugin, it is not initialized, so it doesn't really behave like a static member. It behaves normally from within the main project.

What needs to be done to make this work?

Edit:

If I remove the 'inline' keyword and create a Plugin.cpp file:

Plugin.cpp

#include "Plugin.h"
MyObj* Plugin::obj;

.. then the plugin won't even load anymore, complaining the obj is an undefined symbol.

Edit II:

Accessing the variable from a plugin happens like so:

TestPlugin.h

#ifndef TESTPLUGIN_H
#define TESTPLUGIN_H
#include "/path/to/Plugin.h"
class TestPlugin:public Plugin
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "TestPlugin" FILE "metadata.json")
    Q_INTERFACES(Plugin)
public:
    TestPlugin();
};

TestPlugin.cpp

#include "TestPlugin.h"
TestPlugin::TestPlugin()
{
    qDebug() << obj; // obj is uninitialized here
}

Edit III:

To put any and all discussion to rest whether obj is initialized;

here's how it's done:

#include "Plugin.h"
#include "MyObj.h"
MainProject::MainProject()
{
...
Plugin::obj=new MyObj();
qDebug() << Plugin::obj; // there, initialized successfully
...
loadPlugins();
...
}
Ralf Van Bogaert
  • 103
  • 1
  • 10
  • It allows me to keep the class header only. I updated the original question. – Ralf Van Bogaert May 25 '23 at 12:09
  • Uh no, this is how static variables are declared? If I remove it I can't compile my main project anymore, complaining that Plugin::obj is an undefined reference. – Ralf Van Bogaert May 25 '23 at 12:20
  • 1
    @RalfVanBogaert No i mean remove the `inline` in the header when you're defining the variable in another source file. See [demo](https://onlinegdb.com/OYquprRxgj) – Jason May 25 '23 at 12:23
  • @Jason This is exactly what OP did (look at the edit) – Fareanor May 25 '23 at 12:28
  • @Fareanor I see, then most probably [static initialization order "fiasco", C++](https://stackoverflow.com/questions/29822181/prevent-static-initialization-order-fiasco-c) – Jason May 25 '23 at 12:30
  • @RalfVanBogaert _[...] if I try to access the pointer from a plugin, it is not initialized[...]_ Yes because it is not. Your pointer is declared but you did not initialize it. Accessing it is then undefined behaviour. Whether you use `inline` or you define it in a source file, you have to initialize it (which you did not). – Fareanor May 25 '23 at 12:34
  • Yes I did, I mentioned clearly that the object is initialized *before loading any plugins*. – Ralf Van Bogaert May 25 '23 at 13:17
  • What do you mean by ***trying to access the pointer from a plugin***?! Can you show how you intend to access it? – Red.Wave May 25 '23 at 13:54
  • Why? Sound like trying solve some other problem in wrong way. Also why you have `inline` there? – Marek R May 25 '23 at 13:55
  • @Marek R: I have inline there to avoid needing a Plugin.cpp. But I don't mind removing inline and having one if it fixed the problem. – Ralf Van Bogaert May 25 '23 at 14:03
  • @Red.Wave: I updated the original question. – Ralf Van Bogaert May 25 '23 at 14:04
  • Maybe using a singleton would be a good solution. If it's not initialized, it will be at your first attempt to access the object any way. It relates to "the author advises to wrap the static variables into functions, thus to prevent the "fiasco" by maintaining the creation order of variables" from @Jason link. If it's not a singleton that you need, just wrap it in a function. – René paul Debroize May 25 '23 at 14:28
  • Now I can affirm that this static pointer is uninitialized and it is improperly used. Why did you leave it uninitialized in the 1st place?! – Red.Wave May 25 '23 at 15:51
  • Like I said several times now - it *is* initialized. I initialize it well before any plugins are loaded. It's just not shown in any of the code above. I *assure* you it is initialized. – Ralf Van Bogaert May 25 '23 at 17:57
  • I added some code how it is initialized – Ralf Van Bogaert May 25 '23 at 18:08

1 Answers1

0

You're never setting obj to anything, so it's uninitialized. You can do this instead:

#ifndef PLUGIN_H
#define PLUGIN_H
class Plugin:public QObject
{
public:
    inline static MyObj* obj = nullptr;
};
Q_DECLARE_INTERFACE(Plugin,Plugin_iid)
#endif

then it is initialized to nullptr. You can replace nullptr with the pointer you'd like to put there. This works because you declared it inline.

lionkor
  • 562
  • 2
  • 18