c++qt5.2vrpn

Function call missing argument list to create pointer


I tried to connect my app to OpenViBE through VRPN server. My app works well until I try to add code to connect my app to VRPN server.

My code looks like this:

MainWindow.c code:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtUiTools/QUiLoader>
#include <QFile>
#include <QMessageBox>
#include <QFileDialog>

#include <iostream>
using namespace std;

#include "vrpn_Analog.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    currentImage = 0;
    labelSize = ui->label_2->size();

    createActions();
    openFileDialog();
}
void MainWindow::checkChannels()
{
    vrpn_Analog_Remote *vrpnAnalog = new vrpn_Analog_Remote("Mouse0@localhost");
    vrpnAnalog->register_change_handler( 0, handle_analog );
}


void VRPN_CALLBACK MainWindow::handle_analog( void* userData, const vrpn_ANALOGCB a )
{
 int nbChannels = a.num_channel;

 cout << "Analog : ";

 for( int i=0; i < a.num_channel; i++ )
 {
 cout << a.channel[i] << " ";
 }

 cout << endl;
}

MainWindow.h code:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFileInfoList>

#include "vrpn_Analog.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

protected:
    void resizeEvent(QResizeEvent *);

private slots:
    void openFileDialog();    

private:    
    void checkChannels();

    void VRPN_CALLBACK handle_analog( void* userData, const vrpn_ANALOGCB a );

};

#endif // MAINWINDOW_H

With this code, when I try to run my app I get:

error: C3867: 'MainWindow::handle_analog': function call missing argument list; use '&MainWindow::handle_analog' to create a pointer to member

I try to edit code by error advice, but I get another error:

error: C2664: 'vrpn_Analog_Remote::register_change_handler' : cannot convert parameter 2 from 'void (__stdcall MainWindow::* )(void *,const vrpn_ANALOGCB)' to 'vrpn_ANALOGCHANGEHANDLER'
There is no context in which this conversion is possible

I search around, but I don't find any usable solution.

Methods checkChannels and handle_analog I "copy" from this code, where all works fine:

#include <QtCore/QCoreApplication>
#include <iostream>
#include "vrpn_Analog.h"


void VRPN_CALLBACK vrpn_analog_callback(void* user_data, vrpn_ANALOGCB analog)
{
    for (int i = 0; i < analog.num_channel; i++)
    {
        if (analog.channel[i] > 0)
        {

            std::cout << "Analog Channel : " << i << " / Analog Value : " << analog.channel[i] << std::endl;
        }
    }
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    /* flag used to stop the program execution */
    bool running = true;

    /* VRPN Analog object */
    vrpn_Analog_Remote* VRPNAnalog;

    /* Binding of the VRPN Analog to a callback */
    VRPNAnalog = new vrpn_Analog_Remote("openvibe_vrpn_analog@localhost");
    VRPNAnalog->register_change_handler(NULL, vrpn_analog_callback);

    /* The main loop of the program, each VRPN object must be called in order to process data */
    while (running)
    {
        VRPNAnalog->mainloop();
    }

    return 0;

    return a.exec();
}

Where I'm doing mistake? Thanks for all replies.


Solution

  • You cannot directly call a non-static class method using this callback. This is because the method is expecting to be called with the class this pointer.

    If you don't need any data from your class, then just make the method static. If you do need data from the class, you can make a static "stub" that takes the class pointer in the userData parameter and then calls the original method. Something like:

    Declaration:

    static void VRPN_CALLBACK handle_analog_stub( void* userData, const vrpn_ANALOGCB a );
    

    Definition

    void VRPN_CALLBACK MainWindow::handle_analog_stub( void* userData, const vrpn_ANALOGCB a )
    {
       MainWindow *mainWindow = static_cast<MainWindow*>(userData);
       mainWindow->handle_analog(NULL, a);
    }
    

    Then when you call the function use:

    vrpnAnalog->register_change_handler( this, handle_analog_stub );
    

    (Updated to static_cast to pointer, thanks rpavlik)