Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. connect: External "C" function
Forum Updated to NodeBB v4.3 + New Features

connect: External "C" function

Scheduled Pinned Locked Moved Solved General and Desktop
16 Posts 4 Posters 2.0k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • JonBJ JonB

    @fem_dev
    You are missing where @jsulm / @JKSH said:

    Then define pluginInstance in one of your cpp files (main.cpp for example)

    You need the line reading

    Plugin *pluginInstance = nullptr; // This pointer can be updated when you construct your plugin object
    

    in your main application. Once, in one of its .cpp files.. Note that is without the extern. Where do you have this?

    Explanation:

    Your shared library has extern Plugin *pluginInstance; in it. That means it says "there is/must be a pluginInstance out there, which I can use". That is what extern means. So it compiles.

    When you come to load at run-time, your program needs to have defined this pluginInstance, to provide this variable. Without it you get undefined symbol. The statement Plugin *pluginInstance, without the extern, defines the symbol. That is needed in some one (and only one) .cpp file of the main application loading your shared library.

    F Offline
    F Offline
    fem_dev
    wrote on last edited by
    #7

    @JonB Almost there...

    My shared library (plugin) have a Interface Class called Plugin_API as you can see below:

    class PLUGIN_EXPORT Plugin : public Plugin_API
    {
        Q_OBJECT
        Q_PLUGIN_METADATA(IID "com.rotortest.plugin")
        Q_INTERFACES(Plugin_API)
    ...
    }
    

    So, inside my main application I have the same Plugin_API Interface...not the Plugin class.
    I think that the extern variable declaration must be PluginAPI type in both Qt projects (plugin and main application), right?

    #include <iostream>
    #include "plugin.h"
    #include "dialog.h"
    
    extern Plugin_API *pluginInstance; // Changed from 'Plugin' to 'Plugin_API'
    
    Plugin::Plugin(QObject* parent)
    {
    }
    
    void Plugin::receivedMsg(int msgType, char* msg)
    {
    }
    
    void fortranMsg(int msgType, char* msg)
    {
        std::cout << msgType << " | " << msg << std::endl;
    
        if (pluginInstance)
             pluginInstance->receivedMsg(msgType, msg);
    }
    

    In my main application project, I opened the main GUI window Widget (called: App.cpp) and tried to add this line below:

    #include "app.h"
    #include "ui_app.h"
    
    Plugin_API *pluginInstance = nullptr;
    
    App::App(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::App)
    {
        ui->setupUi(this);
    ...
    }
    

    But I got the same run time error:

    libLobular-Bearing.so: undefined symbol: pluginInstance
    

    I tried to change the pointer value inside the App:loadPlugins() method (as you can see below) but without success too.

    void App::loadPlugins(const QStringList pluginsList)
    {
        foreach(QString file, pluginsList) {
    
            QPluginLoader loader(file);
    
            // Error checking:
            if (!loader.load()) {
                sendErrorMsg(tr("%1: ").arg(loader.errorString()));
                continue;
            }
    
            // Get and display the plugin file name:
            const QStringList pathSplited = loader.fileName().split("/");
            const QString fileName = pathSplited.last();
            sendStatusMsg(tr("Loading plugin: %1").arg(fileName));
    
            // Cast plugin interface:
            Plugin_API* plugin = qobject_cast<Plugin_API*>(loader.instance());
    
            // Error chekcing: nullptr
            if (!plugin) {
                sendErrorMsg(tr("Wrong Plugin API! Could not cast: %1").arg(loader.fileName()));
                continue;
            }
    
            // ===== CONNECT ALL SIGNALS /  SLOTS ===== //
            bool conn1 = connect(plugin, &Plugin_API::sendMsg, this, &App::receivedMsg);
            bool conn2 = connect(plugin, &Plugin_API::savePluginSettings, this, &App::receivedPluginSettings);
    
            bool allConnections = conn1 & conn2;
    
            if (!allConnections) {
                sendErrorMsg(tr("Unable to connect: %1").arg(plugin->getName()));
                continue;
            }
    
            pluginInstance = plugin; // TRY TO USE THE POINTER
    
            // Store the plugin in a map:
            _pluginsMapMap[plugin->getType()][plugin->getName()] = plugin;
        }
    }
    

    Could you please help me a little bit more?
    How can I fix it?

    jsulmJ JonBJ 2 Replies Last reply
    0
    • F fem_dev

      @JonB Almost there...

      My shared library (plugin) have a Interface Class called Plugin_API as you can see below:

      class PLUGIN_EXPORT Plugin : public Plugin_API
      {
          Q_OBJECT
          Q_PLUGIN_METADATA(IID "com.rotortest.plugin")
          Q_INTERFACES(Plugin_API)
      ...
      }
      

      So, inside my main application I have the same Plugin_API Interface...not the Plugin class.
      I think that the extern variable declaration must be PluginAPI type in both Qt projects (plugin and main application), right?

      #include <iostream>
      #include "plugin.h"
      #include "dialog.h"
      
      extern Plugin_API *pluginInstance; // Changed from 'Plugin' to 'Plugin_API'
      
      Plugin::Plugin(QObject* parent)
      {
      }
      
      void Plugin::receivedMsg(int msgType, char* msg)
      {
      }
      
      void fortranMsg(int msgType, char* msg)
      {
          std::cout << msgType << " | " << msg << std::endl;
      
          if (pluginInstance)
               pluginInstance->receivedMsg(msgType, msg);
      }
      

      In my main application project, I opened the main GUI window Widget (called: App.cpp) and tried to add this line below:

      #include "app.h"
      #include "ui_app.h"
      
      Plugin_API *pluginInstance = nullptr;
      
      App::App(QWidget *parent)
          : QMainWindow(parent)
          , ui(new Ui::App)
      {
          ui->setupUi(this);
      ...
      }
      

      But I got the same run time error:

      libLobular-Bearing.so: undefined symbol: pluginInstance
      

      I tried to change the pointer value inside the App:loadPlugins() method (as you can see below) but without success too.

      void App::loadPlugins(const QStringList pluginsList)
      {
          foreach(QString file, pluginsList) {
      
              QPluginLoader loader(file);
      
              // Error checking:
              if (!loader.load()) {
                  sendErrorMsg(tr("%1: ").arg(loader.errorString()));
                  continue;
              }
      
              // Get and display the plugin file name:
              const QStringList pathSplited = loader.fileName().split("/");
              const QString fileName = pathSplited.last();
              sendStatusMsg(tr("Loading plugin: %1").arg(fileName));
      
              // Cast plugin interface:
              Plugin_API* plugin = qobject_cast<Plugin_API*>(loader.instance());
      
              // Error chekcing: nullptr
              if (!plugin) {
                  sendErrorMsg(tr("Wrong Plugin API! Could not cast: %1").arg(loader.fileName()));
                  continue;
              }
      
              // ===== CONNECT ALL SIGNALS /  SLOTS ===== //
              bool conn1 = connect(plugin, &Plugin_API::sendMsg, this, &App::receivedMsg);
              bool conn2 = connect(plugin, &Plugin_API::savePluginSettings, this, &App::receivedPluginSettings);
      
              bool allConnections = conn1 & conn2;
      
              if (!allConnections) {
                  sendErrorMsg(tr("Unable to connect: %1").arg(plugin->getName()));
                  continue;
              }
      
              pluginInstance = plugin; // TRY TO USE THE POINTER
      
              // Store the plugin in a map:
              _pluginsMapMap[plugin->getType()][plugin->getName()] = plugin;
          }
      }
      

      Could you please help me a little bit more?
      How can I fix it?

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #8

      @fem_dev said in connect: External "C" function:

      In my main application project, I opened the main GUI window Widget (called: App.cpp) and tried to add this line below:

      This does not make sense as pluginInstance is declared in the plug-in NOT in the application! You do not need that in main application at all - simply include the header file which contains extern Plugin_API *pluginInstance; - this is what I actually suggested before.
      To make it short:

      • Add extern Plugin_API *pluginInstance; to the header file inside plug-in NOT cpp file
      • Add Plugin_API *pluginInstance = nullptr; to the corresponding cpp file inside plug-in
      • Do NOT add Plugin_API *pluginInstance = nullptr; in main application
      • Read about "extern", for example https://riptutorial.com/cplusplus/example/28730/extern

      But, I'm wondering why you don't simply add pluginInstance as static member to Plugin_API...

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      F 1 Reply Last reply
      3
      • F fem_dev

        @JonB Almost there...

        My shared library (plugin) have a Interface Class called Plugin_API as you can see below:

        class PLUGIN_EXPORT Plugin : public Plugin_API
        {
            Q_OBJECT
            Q_PLUGIN_METADATA(IID "com.rotortest.plugin")
            Q_INTERFACES(Plugin_API)
        ...
        }
        

        So, inside my main application I have the same Plugin_API Interface...not the Plugin class.
        I think that the extern variable declaration must be PluginAPI type in both Qt projects (plugin and main application), right?

        #include <iostream>
        #include "plugin.h"
        #include "dialog.h"
        
        extern Plugin_API *pluginInstance; // Changed from 'Plugin' to 'Plugin_API'
        
        Plugin::Plugin(QObject* parent)
        {
        }
        
        void Plugin::receivedMsg(int msgType, char* msg)
        {
        }
        
        void fortranMsg(int msgType, char* msg)
        {
            std::cout << msgType << " | " << msg << std::endl;
        
            if (pluginInstance)
                 pluginInstance->receivedMsg(msgType, msg);
        }
        

        In my main application project, I opened the main GUI window Widget (called: App.cpp) and tried to add this line below:

        #include "app.h"
        #include "ui_app.h"
        
        Plugin_API *pluginInstance = nullptr;
        
        App::App(QWidget *parent)
            : QMainWindow(parent)
            , ui(new Ui::App)
        {
            ui->setupUi(this);
        ...
        }
        

        But I got the same run time error:

        libLobular-Bearing.so: undefined symbol: pluginInstance
        

        I tried to change the pointer value inside the App:loadPlugins() method (as you can see below) but without success too.

        void App::loadPlugins(const QStringList pluginsList)
        {
            foreach(QString file, pluginsList) {
        
                QPluginLoader loader(file);
        
                // Error checking:
                if (!loader.load()) {
                    sendErrorMsg(tr("%1: ").arg(loader.errorString()));
                    continue;
                }
        
                // Get and display the plugin file name:
                const QStringList pathSplited = loader.fileName().split("/");
                const QString fileName = pathSplited.last();
                sendStatusMsg(tr("Loading plugin: %1").arg(fileName));
        
                // Cast plugin interface:
                Plugin_API* plugin = qobject_cast<Plugin_API*>(loader.instance());
        
                // Error chekcing: nullptr
                if (!plugin) {
                    sendErrorMsg(tr("Wrong Plugin API! Could not cast: %1").arg(loader.fileName()));
                    continue;
                }
        
                // ===== CONNECT ALL SIGNALS /  SLOTS ===== //
                bool conn1 = connect(plugin, &Plugin_API::sendMsg, this, &App::receivedMsg);
                bool conn2 = connect(plugin, &Plugin_API::savePluginSettings, this, &App::receivedPluginSettings);
        
                bool allConnections = conn1 & conn2;
        
                if (!allConnections) {
                    sendErrorMsg(tr("Unable to connect: %1").arg(plugin->getName()));
                    continue;
                }
        
                pluginInstance = plugin; // TRY TO USE THE POINTER
        
                // Store the plugin in a map:
                _pluginsMapMap[plugin->getType()][plugin->getName()] = plugin;
            }
        }
        

        Could you please help me a little bit more?
        How can I fix it?

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by
        #9

        @fem_dev
        Briefly, I had slightly misunderstood, and taken your word that pluginInstance was to be defined in your main program. From @jsulm I now understand it is to work the other way round: you will define it in your shared library, and export it (extern) to be accessible from your main. The explanation about extern Plugin_API *pluginInstance declaration can appear many times (e.g. in a .h file) while the Plugin_API *pluginInstance definition must appear just once in a .cpp file remains the same.

        You should follow exactly what @jsulm has instructed. If as he says you do not need to access pluginInstance outside of the shared library at all, you may be able to just define it as static there.

        1 Reply Last reply
        1
        • F fem_dev

          Thank you @JKSH for your quick response...

          @JKSH said in connect: External "C" function:

          There are many ways you could implement the exporting function.

          I think that I need some help to understand in which scope should I write this lines...

          The problem is: Only inside the main application I can write something like this:

          Plugin *pluginInstance = nullptr; // This pointer can be updated when you construct your plugin object
          

          Because each plugin is loaded by the main application using QPluginLoader.
          So, I think that I can't use this line above inside the Plugin class. Am I right?

          Here is my plugin.h header file:

          #include "dialog.h"
          #include "plugin_global.h"
          #include "plugin_qt_api.h"
          
          // Fortran subroutines
          extern "C" {
              void callFortran(...input arguments ....);
              void fortranMsg(int msgType, char* msg);
          }
          
          class PLUGIN_EXPORT Plugin : public Plugin_API
          {
              Q_OBJECT
              Q_PLUGIN_METADATA(IID "com.rotortest.plugin")
              Q_INTERFACES(Plugin_API)
          
          private:
              Dialog _ui;
          
          public:
          
              explicit Plugin(QObject* parent = nullptr);
              ~Plugin();
          
              //... All Methods override
          
              void receiveMsg(int msgType, char* msg);
          };
          

          Here is my plugin.cpp implementation:

          #include <iostream>
          #include "plugin.h"
          #include "dialog.h"
          
          Plugin::Plugin(QObject* parent)
          {
          }
          
          Plugin::~Plugin()
          {
          }
          
          void Plugin::receivedMsg(int msgType, char* msg)
          {
          
          }
          
          void fortranMsg(int msgType, char* msg)
          {
              std::cout << msgType << " | " << msg << std::endl;
          
              // SEND DATA TO A PLUGIN METHOD
              // HOW?
          }
          

          Could you help me pass this data from the fortranMsg () function to the Plugin :: receivedMsg () method?

          A first thought that comes to mind is that I should try to make this connection entirely within the shared library (plugin) project, without resorting to the main application project.
          Or is there a better way to "connect" via the main application?

          JKSHJ Offline
          JKSHJ Offline
          JKSH
          Moderators
          wrote on last edited by
          #10

          @fem_dev said in connect: External "C" function:

          Because each plugin is loaded by the main application using QPluginLoader.
          So, I think that I can't use this line above inside the Plugin class. Am I right?

          You are right, the example code that I wrote must be placed in your main application, not your plugin.

          Note: That example expects a single plugin instance. If you want to load multiple plugins at the same time, then you'll need a vector of pointers, not just a single pointer.

          A first thought that comes to mind is that I should try to make this connection entirely within the shared library (plugin) project, without resorting to the main application project.

          I don't think that's a good design. A plugin should not be aware of the main application, so a plugin shouldn't be expected to know that fortranMsg() exists.

          The main application should load the plugin and make all necessary "connections" to the plugin.

          Or is there a better way to "connect" via the main application?

          Let's step back a bit. Ignore the Fortran code for now.

          How do you currently pass any data from your main application into your plugin objects?

          Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

          1 Reply Last reply
          3
          • jsulmJ jsulm

            @fem_dev said in connect: External "C" function:

            In my main application project, I opened the main GUI window Widget (called: App.cpp) and tried to add this line below:

            This does not make sense as pluginInstance is declared in the plug-in NOT in the application! You do not need that in main application at all - simply include the header file which contains extern Plugin_API *pluginInstance; - this is what I actually suggested before.
            To make it short:

            • Add extern Plugin_API *pluginInstance; to the header file inside plug-in NOT cpp file
            • Add Plugin_API *pluginInstance = nullptr; to the corresponding cpp file inside plug-in
            • Do NOT add Plugin_API *pluginInstance = nullptr; in main application
            • Read about "extern", for example https://riptutorial.com/cplusplus/example/28730/extern

            But, I'm wondering why you don't simply add pluginInstance as static member to Plugin_API...

            F Offline
            F Offline
            fem_dev
            wrote on last edited by fem_dev
            #11

            @jsulm thank you...I'm almost there...
            Here are my modifications:

            Here is my plugin.h header file:

            #include "dialog.h"
            #include "plugin_global.h"
            #include "plugin_qt_api.h"
            
            extern Plugin_API *pluginInstance; // FIRST MODIFICATION
            
            // Fortran interface
            extern "C" {
                void fortranMsg(int msgType, char* msg);
            }
            
            class PLUGIN_EXPORT Plugin : public Plugin_API
            {
                Q_OBJECT
                Q_PLUGIN_METADATA(IID "com.rotortest.plugin")
                Q_INTERFACES(Plugin_API)
            
            private:
                Dialog _ui;
            
            public:
            
                explicit Plugin(QObject* parent = nullptr);
                ~Plugin();
            
                ...
            }
            

            Here is my plugin.cpp implementation file:

            #include "plugin.h"
            #include <iostream>
            
            #include "dialog.h"
            
            Plugin_API* pluginInstance = nullptr; // SECOND MODIFICATION
            
            Plugin::Plugin(QObject* parent)
            {
                Q_UNUSED(parent)
            }
            
            // Other Plugin method implementations...
            

            And inside the plugin.cpp I have:

            void fortranMsg(int msgType, char* msg)
            {
                std::cout << msgType << " | " << msg << std::endl; // PRINT THE MSG IN THE Qt CONSOLE OK
            
                if (pluginInstance) {
                    pluginInstance->sendStatusMsg(QString(msg));
                } else {
                    std::cout << "pluginInstance is NULL" << std::endl; // ALWAYS NULLPTR
                }
            }
            

            I do NOT declared `pluginInstance` in my `main application` // LAST MODIFICATION
            

            I got a clean build. No errors, no warnings! All good!
            And I don't got any run-time erros, BUT I got always the same console message:

            pluginInstance is NULL
            

            After that, I tried too:

            Plugin_API* pluginInstance = nullptr; // SECOND MODIFICATION
            
            Plugin::Plugin(QObject* parent)
            {
                Q_UNUSED(parent)
                
                pluginInstance = new Plugin; // CREATE A VALID INSTANCE
            }
            

            In this case, the pluginInstance is NULL console message disapears (the pointer is valid), BUT it is not calling correctly the Plugin::sendStatusMsg() method as I want.
            So, I don't know why, I don't get the sent plugin message in my main application.

            @JKSH here is how I communicate my own Plugin with my main application:
            First, the plugin_qt_api.h:

            #ifndef PLUGIN_QT_API_H
            #define PLUGIN_QT_API_H
            
            #include <QtPlugin>
            #include <QString>
            
            #include "message_types.h"
            
            class Plugin_API : public QObject
            {
                Q_OBJECT
            
            public:
                 Plugin_API()  {}
            
                virtual ~Plugin_API() = default;
            
                ...
                
                virtual void sendStatusMsg(const QString& msg) = 0;
            
            signals:
                void sendMsg(QString source, MSG_TYPE msgType, QString msg);
            };
            
            Q_DECLARE_INTERFACE(Plugin_API, "com.rotortest.plugin")
            
            #endif // PLUGIN_QT_API_H
            

            Second, the plugin.h:

            #include "plugin_global.h"
            #include "plugin_qt_api.h"
            
            extern Plugin_API *pluginInstance;
            
            // Fortran subroutines
            extern "C" {
                void fortranMsg(int msgType, char* msg);
            }
            
            class PLUGIN_EXPORT Plugin : public Plugin_API
            {
                Q_OBJECT
                Q_PLUGIN_METADATA(IID "com.rotortest.plugin")
                Q_INTERFACES(Plugin_API)
            
            public:
            
                explicit Plugin(QObject* parent = nullptr);
            
                ~Plugin();
            
                ...
                void sendStatusMsg(const QString &msg) override;
            };
            

            Finally, the Plugin::sendStatusMsg() method implementation inside the plugin.cpp file:

            void Plugin::sendStatusMsg(const QString& msg) {
                emit sendMsg("My Plugin", MSG_TYPE::STATUS_MSG, msg);
            }
            

            This plugin method works good if I call it from a method inside the Plugin class. No problems here!
            My problem is ONLY when I have to call this method from the fortranMsg() function. Because it is a function and NOT a Plugin method.

            So, when my Fortran send a message to the C++ side, I got the message correctly in the fortranMsg() function (I can see it on Qt console), but I don't know how to pass this received message to the Plugin::sendStatusMsg() method.

            I want to do that to enable my plugins always use the same plugin method to send messages from the plugin side to my main application.

            As you can see above, inside my main application, I have a method called App::loadPlugin().
            Inside of it, I have:

            @fem_dev said in connect: External "C" function:

            bool conn1 = connect(plugin, &Plugin_API::sendMsg, this, &App::receivedMsg);

            Could you help me?

            F 1 Reply Last reply
            0
            • F fem_dev

              @jsulm thank you...I'm almost there...
              Here are my modifications:

              Here is my plugin.h header file:

              #include "dialog.h"
              #include "plugin_global.h"
              #include "plugin_qt_api.h"
              
              extern Plugin_API *pluginInstance; // FIRST MODIFICATION
              
              // Fortran interface
              extern "C" {
                  void fortranMsg(int msgType, char* msg);
              }
              
              class PLUGIN_EXPORT Plugin : public Plugin_API
              {
                  Q_OBJECT
                  Q_PLUGIN_METADATA(IID "com.rotortest.plugin")
                  Q_INTERFACES(Plugin_API)
              
              private:
                  Dialog _ui;
              
              public:
              
                  explicit Plugin(QObject* parent = nullptr);
                  ~Plugin();
              
                  ...
              }
              

              Here is my plugin.cpp implementation file:

              #include "plugin.h"
              #include <iostream>
              
              #include "dialog.h"
              
              Plugin_API* pluginInstance = nullptr; // SECOND MODIFICATION
              
              Plugin::Plugin(QObject* parent)
              {
                  Q_UNUSED(parent)
              }
              
              // Other Plugin method implementations...
              

              And inside the plugin.cpp I have:

              void fortranMsg(int msgType, char* msg)
              {
                  std::cout << msgType << " | " << msg << std::endl; // PRINT THE MSG IN THE Qt CONSOLE OK
              
                  if (pluginInstance) {
                      pluginInstance->sendStatusMsg(QString(msg));
                  } else {
                      std::cout << "pluginInstance is NULL" << std::endl; // ALWAYS NULLPTR
                  }
              }
              

              I do NOT declared `pluginInstance` in my `main application` // LAST MODIFICATION
              

              I got a clean build. No errors, no warnings! All good!
              And I don't got any run-time erros, BUT I got always the same console message:

              pluginInstance is NULL
              

              After that, I tried too:

              Plugin_API* pluginInstance = nullptr; // SECOND MODIFICATION
              
              Plugin::Plugin(QObject* parent)
              {
                  Q_UNUSED(parent)
                  
                  pluginInstance = new Plugin; // CREATE A VALID INSTANCE
              }
              

              In this case, the pluginInstance is NULL console message disapears (the pointer is valid), BUT it is not calling correctly the Plugin::sendStatusMsg() method as I want.
              So, I don't know why, I don't get the sent plugin message in my main application.

              @JKSH here is how I communicate my own Plugin with my main application:
              First, the plugin_qt_api.h:

              #ifndef PLUGIN_QT_API_H
              #define PLUGIN_QT_API_H
              
              #include <QtPlugin>
              #include <QString>
              
              #include "message_types.h"
              
              class Plugin_API : public QObject
              {
                  Q_OBJECT
              
              public:
                   Plugin_API()  {}
              
                  virtual ~Plugin_API() = default;
              
                  ...
                  
                  virtual void sendStatusMsg(const QString& msg) = 0;
              
              signals:
                  void sendMsg(QString source, MSG_TYPE msgType, QString msg);
              };
              
              Q_DECLARE_INTERFACE(Plugin_API, "com.rotortest.plugin")
              
              #endif // PLUGIN_QT_API_H
              

              Second, the plugin.h:

              #include "plugin_global.h"
              #include "plugin_qt_api.h"
              
              extern Plugin_API *pluginInstance;
              
              // Fortran subroutines
              extern "C" {
                  void fortranMsg(int msgType, char* msg);
              }
              
              class PLUGIN_EXPORT Plugin : public Plugin_API
              {
                  Q_OBJECT
                  Q_PLUGIN_METADATA(IID "com.rotortest.plugin")
                  Q_INTERFACES(Plugin_API)
              
              public:
              
                  explicit Plugin(QObject* parent = nullptr);
              
                  ~Plugin();
              
                  ...
                  void sendStatusMsg(const QString &msg) override;
              };
              

              Finally, the Plugin::sendStatusMsg() method implementation inside the plugin.cpp file:

              void Plugin::sendStatusMsg(const QString& msg) {
                  emit sendMsg("My Plugin", MSG_TYPE::STATUS_MSG, msg);
              }
              

              This plugin method works good if I call it from a method inside the Plugin class. No problems here!
              My problem is ONLY when I have to call this method from the fortranMsg() function. Because it is a function and NOT a Plugin method.

              So, when my Fortran send a message to the C++ side, I got the message correctly in the fortranMsg() function (I can see it on Qt console), but I don't know how to pass this received message to the Plugin::sendStatusMsg() method.

              I want to do that to enable my plugins always use the same plugin method to send messages from the plugin side to my main application.

              As you can see above, inside my main application, I have a method called App::loadPlugin().
              Inside of it, I have:

              @fem_dev said in connect: External "C" function:

              bool conn1 = connect(plugin, &Plugin_API::sendMsg, this, &App::receivedMsg);

              Could you help me?

              F Offline
              F Offline
              fem_dev
              wrote on last edited by fem_dev
              #12

              @fem_dev Thank you @JKSH @jsulm and @JonB for all help in this topic! I really need to say "thank you"! You all are great!

              With your help I finally solve this problem.

              Here is my plugin.h header file:

              extern Plugin_API *pluginInstance; // <-- 1. CREATE A GLOBAL INTERFACE CLASS POINTER
              
              extern "C" {
                  void fortranMsg(int msgType, char* msg);
              }
              
              class PLUGIN_EXPORT Plugin : public Plugin_API
              {
                  Q_OBJECT
                  Q_PLUGIN_METADATA(IID "com.rotortest.plugin")
                  Q_INTERFACES(Plugin_API)
              
              public: 
                  ...
                  void sendStatusMsg(const QString &msg) override;
              }
              

              Here is my plugin.cpp implementation file:

              Plugin_API* pluginInstance = nullptr; // <-- 2. Init the global pointer to nullptr
              
              Plugin::Plugin(QObject* parent)
              {
                  pluginInstance = this; // <-- 3. Point to the current object
              }
              

              Now, I can use the global variable pluginInstance inside a pure function too.
              With this pointer, I can call any Plugin method from any pure function. Like:

              void fortranMsg(int msgType, char* msg)
              {
                  pluginInstance->sendStatusMsg(QString(msg));    
              }
              

              That's it!

              Thank you all again!

              1 Reply Last reply
              1
              • JKSHJ Offline
                JKSHJ Offline
                JKSH
                Moderators
                wrote on last edited by
                #13

                @fem_dev, you're welcome. Happy coding! :)

                I'm curious though: It looks like your app only loads 1 instance of the plugin, is that right? If that's the case, what is the purpose of having a Plugin API?

                Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                F 1 Reply Last reply
                0
                • JKSHJ JKSH

                  @fem_dev, you're welcome. Happy coding! :)

                  I'm curious though: It looks like your app only loads 1 instance of the plugin, is that right? If that's the case, what is the purpose of having a Plugin API?

                  F Offline
                  F Offline
                  fem_dev
                  wrote on last edited by
                  #14

                  @JKSH said in connect: External "C" function:

                  only loads 1 instance of the plugin

                  No @JKSH ...my main application should load many plugins...

                  What part of my code above made you think that my main application only loads a single plugin?

                  Did I write something wrong?

                  JKSHJ 1 Reply Last reply
                  0
                  • F fem_dev

                    @JKSH said in connect: External "C" function:

                    only loads 1 instance of the plugin

                    No @JKSH ...my main application should load many plugins...

                    What part of my code above made you think that my main application only loads a single plugin?

                    Did I write something wrong?

                    JKSHJ Offline
                    JKSHJ Offline
                    JKSH
                    Moderators
                    wrote on last edited by JKSH
                    #15

                    @fem_dev said in connect: External "C" function:

                    No @JKSH ...my main application should load many plugins...

                    What part of my code above made you think that my main application only loads a single plugin?

                    You only have 1 pluginInstance pointer. That means fortranMsg() can only send the message to 1 plugin.

                    Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                    F 1 Reply Last reply
                    0
                    • JKSHJ JKSH

                      @fem_dev said in connect: External "C" function:

                      No @JKSH ...my main application should load many plugins...

                      What part of my code above made you think that my main application only loads a single plugin?

                      You only have 1 pluginInstance pointer. That means fortranMsg() can only send the message to 1 plugin.

                      F Offline
                      F Offline
                      fem_dev
                      wrote on last edited by
                      #16

                      @JKSH said in connect: External "C" function:

                      You only have 1 pluginInstance pointer.

                      Yes! That's right!

                      Inside my plugin, I have only one pluginInstance pointer.

                      Each plugin is a isolated Qt shared library project. So inside of each plugin I must have only your own pluginInstance pointer.

                      My main application will load all compiled plugins after that.

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved