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. Emit signal from static function issue
Forum Updated to NodeBB v4.3 + New Features

Emit signal from static function issue

Scheduled Pinned Locked Moved Unsolved General and Desktop
15 Posts 4 Posters 8.3k 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.
  • Cobra91151C Offline
    Cobra91151C Offline
    Cobra91151
    wrote on last edited by Cobra91151
    #1

    Hi! I want to emit signal when wlan connection has been registered from static notificationCallBack function.

    Code:
    WirelessConnect.h

    static void WINAPI notificationCallBack(PWLAN_NOTIFICATION_DATA wlanData, PVOID context);
    

    WirelessConnect.cpp

    DWORD dwResult = 0;
    dwResult = WlanRegisterNotification(hClient, WLAN_NOTIFICATION_SOURCE_ALL, TRUE, notificationCallBack, NULL, NULL, &dwPrevNotif);
    
    void WINAPI WirelessConnect::notificationCallBack(PWLAN_NOTIFICATION_DATA wlanData, PVOID context)
    {
        context = NULL;
        switch (wlanData->NotificationCode) {
            case wlan_notification_acm_connection_complete:
                emit apConnectionComplete();
                qDebug() << "Connected!";
            break;
    
            case wlan_notification_acm_connection_attempt_fail:
                emit apConnectionFailed();
                qDebug() << "Failed!";
            break;
    
            default:
                break;
        }
    }
    

    Test .cpp:

    WirelessConnect *wirelessAPConnect = new WirelessConnect();
    connect(wirelessAPConnect, &WirelessConnect::apConnectionComplete, setAPConnection);
    connect(wirelessAPConnect, &WirelessConnect::apConnectionFailed, setAPConnectionFailed);
    

    The problem is error: C2355: 'this': can only be referenced inside non-static member functions or non-static data member initializers.

    So how to emit signal from the static function, for example to display QMessageBox about the wlan connection in Test class? Thanks in advance.

    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      Static method does not construct an object, so there is no object which could emit the signal. That's why it is forbidden.

      Can you change the method so that it is not static? A const method should be enough.

      If you absolutely have to keep the method static, you can add a QObject parameter and pass there an object which will emit the signal instead of your notificationCallBack method.

      (Z(:^

      Cobra91151C 1 Reply Last reply
      4
      • sierdzioS sierdzio

        Static method does not construct an object, so there is no object which could emit the signal. That's why it is forbidden.

        Can you change the method so that it is not static? A const method should be enough.

        If you absolutely have to keep the method static, you can add a QObject parameter and pass there an object which will emit the signal instead of your notificationCallBack method.

        Cobra91151C Offline
        Cobra91151C Offline
        Cobra91151
        wrote on last edited by
        #3

        @sierdzio

        Yes, notificationCallBack is required by WlanRegisterNotification function, and it should be only static.

        If you absolutely have to keep the method static, you can add a QObject parameter and pass there an object which will emit the signal instead of your notificationCallBack method.

        You mean for example, static Test::notificationCallBack pass it to WlanRegisterNotification? Thanks.

        VRoninV 1 Reply Last reply
        0
        • Cobra91151C Cobra91151

          @sierdzio

          Yes, notificationCallBack is required by WlanRegisterNotification function, and it should be only static.

          If you absolutely have to keep the method static, you can add a QObject parameter and pass there an object which will emit the signal instead of your notificationCallBack method.

          You mean for example, static Test::notificationCallBack pass it to WlanRegisterNotification? Thanks.

          VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by VRonin
          #4
          • pass wirelessAPConnect as the pCallbackContext parameter to WlanRegisterNotification
          • remove context = NULL;
          • (optional but recommended) add, at the beginning of the function, Q_ASSERT(dynamic_cast<WirelessConnect*>(context));
          • change emit apConnectionComplete(); to qobject_cast<WirelessConnect*>(context)->apConnectionComplete();
          • change emit apConnectionFailed(); to qobject_cast<WirelessConnect*>(context)->apConnectionFailed();

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          Cobra91151C 2 Replies Last reply
          4
          • VRoninV VRonin
            • pass wirelessAPConnect as the pCallbackContext parameter to WlanRegisterNotification
            • remove context = NULL;
            • (optional but recommended) add, at the beginning of the function, Q_ASSERT(dynamic_cast<WirelessConnect*>(context));
            • change emit apConnectionComplete(); to qobject_cast<WirelessConnect*>(context)->apConnectionComplete();
            • change emit apConnectionFailed(); to qobject_cast<WirelessConnect*>(context)->apConnectionFailed();
            Cobra91151C Offline
            Cobra91151C Offline
            Cobra91151
            wrote on last edited by
            #5

            @VRonin

            Ok. I have changed to:

            void WINAPI WirelessConnect::notificationCallBack(PWLAN_NOTIFICATION_DATA wlanData, PVOID context)
            {
                Q_ASSERT(dynamic_cast<WirelessConnect*>(context));
                switch (wlanData->NotificationCode) {
                    case wlan_notification_acm_connection_complete:
                        qobject_cast<WirelessConnect*>(context)->apConnectionComplete();
                        qDebug() << "Connected!";
                    break;
            
                    case wlan_notification_acm_connection_attempt_fail:
                        qobject_cast<WirelessConnect*>(context)->apConnectionFailed();
                        qDebug() << "Failed!";
                    break;
            
                    default:
                        break;
                }
            }
            
            WirelessConnect wirelessAPConnect; 
            dwResult = WlanRegisterNotification(hClient, WLAN_NOTIFICATION_SOURCE_ALL, TRUE, wirelessAPConnect, NULL, NULL, &dwPrevNotif);
            

            And there are a lot of errors:
            error: C2355: 'this': can only be referenced inside non-static member functions or non-static data member initializers
            error: C2681: 'PVOID': invalid expression type for dynamic_cast
            error: C2665: 'qobject_cast': none of the 2 overloads could convert all the argument types
            error: C2664: 'DWORD WlanRegisterNotification(HANDLE,DWORD,BOOL,WLAN_NOTIFICATION_CALLBACK,PVOID,PVOID,PDWORD)': cannot convert argument 4 from 'WirelessConnect' to 'WLAN_NOTIFICATION_CALLBACK'

            1 Reply Last reply
            0
            • Cobra91151C Offline
              Cobra91151C Offline
              Cobra91151
              wrote on last edited by
              #6

              Then I changed the code to:

              dwResult = WlanRegisterNotification(hClient, WLAN_NOTIFICATION_SOURCE_ALL, TRUE, notificationCallBack, NULL, NULL, &dwPrevNotif);
              
              void WINAPI WirelessConnect::notificationCallBack(PWLAN_NOTIFICATION_DATA wlanData, PVOID context)
              {
                  WirelessConnect *pThis = (WirelessConnect*)context;
                  switch (wlanData->NotificationCode) {
                      case wlan_notification_acm_connection_complete:
                          qobject_cast<WirelessConnect*>(pThis)->apConnectionComplete();
                          qDebug() << "Connected!";
                      break;
              
                      case wlan_notification_acm_connection_attempt_fail:
                          qobject_cast<WirelessConnect*>(pThis)->apConnectionFailed();
                          qDebug() << "Failed!";
                      break;
              
                      default:
                          break;
                  }
              }
              

              By removing Q_ASSERT(dynamic_cast<WirelessConnect*>(context)); some error fixed. But some errors still exists:

              0_1505735072054_2017-09-18_144245.png

              1 Reply Last reply
              0
              • Cobra91151C Offline
                Cobra91151C Offline
                Cobra91151
                wrote on last edited by
                #7

                These errors are with connect:

                connect(wirelessAPConnect, &WirelessConnect::apConnectionComplete, setAPConnection);
                connect(wirelessAPConnect, &WirelessConnect::apConnectionFailed, setAPConnectionFailed);
                

                How to connect static signals/slots? Thanks.

                1 Reply Last reply
                0
                • Cobra91151C Offline
                  Cobra91151C Offline
                  Cobra91151
                  wrote on last edited by Cobra91151
                  #8

                  I have fixed the compile errors.

                  Code:
                  initialized outside of the WirelessConnect class to make it global:
                  static WirelessConnect wirelessConnectObj;

                  void WINAPI WirelessConnect::notificationCallBack(PWLAN_NOTIFICATION_DATA wlanData, PVOID context)
                  {
                      context = NULL;
                      switch (wlanData->NotificationCode) {
                          case wlan_notification_acm_connection_complete:
                              wirelessConnectObj.apConnectionComplete();
                              qDebug() << "Connected!";
                          break;
                  
                          case wlan_notification_acm_connection_attempt_fail:
                              wirelessConnectObj.apConnectionFailed();
                              qDebug() << "Failed!";
                          break;
                  
                          default:
                              break;
                      }
                  }
                  
                  dwResult = WlanRegisterNotification(hClient, WLAN_NOTIFICATION_SOURCE_ALL, TRUE, notificationCallBack, NULL, NULL, &dwPrevNotif);
                  

                  Test.cpp

                  connect(&wirelessConnectObj, &WirelessConnect::apConnectionComplete, this, &Test::setAPConnection);
                  connect(&wirelessConnectObj, &WirelessConnect::apConnectionFailed, this, &Test::setAPConnectionFailed);
                  

                  But nothing executes in the slots. It connects to the wireless network, but nothing is shown in GUI any message, nothing.

                  jsulmJ 1 Reply Last reply
                  1
                  • Cobra91151C Cobra91151

                    I have fixed the compile errors.

                    Code:
                    initialized outside of the WirelessConnect class to make it global:
                    static WirelessConnect wirelessConnectObj;

                    void WINAPI WirelessConnect::notificationCallBack(PWLAN_NOTIFICATION_DATA wlanData, PVOID context)
                    {
                        context = NULL;
                        switch (wlanData->NotificationCode) {
                            case wlan_notification_acm_connection_complete:
                                wirelessConnectObj.apConnectionComplete();
                                qDebug() << "Connected!";
                            break;
                    
                            case wlan_notification_acm_connection_attempt_fail:
                                wirelessConnectObj.apConnectionFailed();
                                qDebug() << "Failed!";
                            break;
                    
                            default:
                                break;
                        }
                    }
                    
                    dwResult = WlanRegisterNotification(hClient, WLAN_NOTIFICATION_SOURCE_ALL, TRUE, notificationCallBack, NULL, NULL, &dwPrevNotif);
                    

                    Test.cpp

                    connect(&wirelessConnectObj, &WirelessConnect::apConnectionComplete, this, &Test::setAPConnection);
                    connect(&wirelessConnectObj, &WirelessConnect::apConnectionFailed, this, &Test::setAPConnectionFailed);
                    

                    But nothing executes in the slots. It connects to the wireless network, but nothing is shown in GUI any message, nothing.

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

                    @Cobra91151 Did you check that connect() calls actually succeeded?
                    Was the callback called?
                    Also using global variables is bad design.

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

                    Cobra91151C 1 Reply Last reply
                    0
                    • jsulmJ jsulm

                      @Cobra91151 Did you check that connect() calls actually succeeded?
                      Was the callback called?
                      Also using global variables is bad design.

                      Cobra91151C Offline
                      Cobra91151C Offline
                      Cobra91151
                      wrote on last edited by Cobra91151
                      #10

                      @jsulm

                      Hi! The callback was called but connect is not working.

                      Also using global variables is bad design.

                      Then how to connect the same static instance in both classes (where signals emits and where it connects)?

                      jsulmJ 1 Reply Last reply
                      0
                      • Cobra91151C Cobra91151

                        @jsulm

                        Hi! The callback was called but connect is not working.

                        Also using global variables is bad design.

                        Then how to connect the same static instance in both classes (where signals emits and where it connects)?

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

                        @Cobra91151 If connect is not working it prints an error at runtime - is there any?

                        How to connect depends on your design/architecture.

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

                        Cobra91151C 1 Reply Last reply
                        0
                        • jsulmJ jsulm

                          @Cobra91151 If connect is not working it prints an error at runtime - is there any?

                          How to connect depends on your design/architecture.

                          Cobra91151C Offline
                          Cobra91151C Offline
                          Cobra91151
                          wrote on last edited by
                          #12

                          @jsulm

                          Sometimes I get at runtime: QObject::disconnect: Unexpected null parameter.

                          1 Reply Last reply
                          0
                          • Cobra91151C Offline
                            Cobra91151C Offline
                            Cobra91151
                            wrote on last edited by Cobra91151
                            #13

                            I have fixed the issue:

                            I set this to the function:

                            
                            WlanRegisterNotification(hClient, WLAN_NOTIFICATION_SOURCE_ALL, TRUE, notificationCallBack, this, NULL, &dwPrevNotif);
                            
                            void WINAPI WirelessConnect::notificationCallBack(PWLAN_NOTIFICATION_DATA wlanData, PVOID context)
                            {
                                //context = NULL;
                                WirelessConnect *pThis = (WirelessConnect*) context;
                                switch (wlanData->NotificationCode) {
                                    case wlan_notification_acm_connection_complete:
                                        pThis->apConnectionComplete();
                                        qDebug() << "Connected!";
                                    break;
                            
                                    case wlan_notification_acm_connection_attempt_fail:
                                        pThis->apConnectionFailed();
                                        qDebug() << "Failed!";
                                    break;
                            
                                    default:
                                        break;
                                }
                            }
                            

                            Then connect it as not static instance:

                            connect(wirelessAPConnect, &WirelessConnect::apConnectionComplete, this, &Test::setAPConnection); 
                            connect(wirelessAPConnect, &WirelessConnect::apConnectionFailed, this, &Test::setAPConnectionFailed);
                            

                            So I don't need the static global instance anymore and it works now.

                            Edited:

                            After some diagnostics (connecting/disconnecting from Access Points), the solution lead to application crash.

                            1 Reply Last reply
                            1
                            • VRoninV VRonin
                              • pass wirelessAPConnect as the pCallbackContext parameter to WlanRegisterNotification
                              • remove context = NULL;
                              • (optional but recommended) add, at the beginning of the function, Q_ASSERT(dynamic_cast<WirelessConnect*>(context));
                              • change emit apConnectionComplete(); to qobject_cast<WirelessConnect*>(context)->apConnectionComplete();
                              • change emit apConnectionFailed(); to qobject_cast<WirelessConnect*>(context)->apConnectionFailed();
                              Cobra91151C Offline
                              Cobra91151C Offline
                              Cobra91151
                              wrote on last edited by Cobra91151
                              #14

                              @VRonin

                              When using this:

                              WirelessConnect *pThis = new WirelessConnect(this);
                               dwResult = WlanRegisterNotification(hClient, WLAN_NOTIFICATION_SOURCE_ALL, TRUE, notificationCallBack, pThis, NULL, &dwPrevNotif);
                              
                              void WINAPI WirelessConnect::notificationCallBack(PWLAN_NOTIFICATION_DATA wlanData, PVOID context)
                              {
                                  Q_ASSERT(dynamic_cast<WirelessConnect*>(context));
                              
                                  switch (wlanData->NotificationCode) {
                                      case wlan_notification_acm_connection_complete:
                                          qobject_cast<WirelessConnect*>(context)->apConnectionComplete();
                                      break;
                              
                                      case wlan_notification_acm_connection_attempt_fail:
                                          qobject_cast<WirelessConnect*>(context)->apConnectionFailed();
                                      break;
                              
                                      default:
                                          break;
                                  }
                              }
                              

                              I get a lot of errors:

                              0_1507324921791_2017-10-07_002151.png

                              Can you describe your solution more properly? Thanks.

                              1 Reply Last reply
                              0
                              • VRoninV Offline
                                VRoninV Offline
                                VRonin
                                wrote on last edited by
                                #15

                                My bad, replace qobject_cast with dynamic_cast, I was trying to over optimise

                                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                ~Napoleon Bonaparte

                                On a crusade to banish setIndexWidget() from the holy land of Qt

                                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