4

VRPN サーバー経由でアプリを OpenViBE に接続しようとしました。アプリを VRPN サーバーに接続するコードを追加しようとするまで、アプリは正常に動作します。

私のコードは次のようになります。

MainWindow.cコード:

#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コード:

#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

このコードを使用して、アプリを実行しようとすると、次のようになります。

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

エラーアドバイスに従ってコードを編集しようとしましたが、別のエラーが発生しました:

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

私は周りを検索しますが、使用可能な解決策が見つかりません。

メソッドcheckChannelshandle_analogこのコードから「コピー」すると、すべて正常に動作します。

#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();
}

私はどこで間違いをしていますか?すべての返信に感謝します。

4

3 に答える 3

4

エラー メッセージは、指定した引数が一致しないことを示していますvrpn_ANALOGCHANGEHANDLER。あなたはその定義を示していません。オンラインでチェックしたところ、提案されました

typedef void (*vrpn_ANALOGCHANGEHANDLER)(void *userdata, const vrpn_ANALOGCB info);

だから私はそれで行きます。

コードは、関数へのポインターに変換できないメンバー関数へのポインターを渡そうとしています。これは、メンバー関数へのポインターはオブジェクトでのみ呼び出すことができるため、使用するオブジェクトがわからないためです。

「コピーオフ」しているコードを見ると、それvrpn_analog_callbackが無料の機能であることがわかります。ただし、コードではメンバー関数です。コールバックがフリー関数 (または静的メンバー関数) になるようにコードを変更する必要があります。

ハンドラーを登録しているのと同じ MainWindow オブジェクトでコールバックがメンバー関数を呼び出す必要がある場合は、次のようにします。

// In MainWindow's class definition, add this:
static void VRPN_CALLBACK cb_handle_analog( void* userData, const vrpn_ANALOGCB a )
{
    static_cast<MainWindow *>(userData)->handle_analog(NULL, a);
}

// In checkChannels()
vrpnAnalog->register_change_handler( this, cb_handle_analog );
于 2014-04-22T00:11:00.990 に答える
3

このコールバックを使用して非静的クラス メソッドを直接呼び出すことはできません。これは、メソッドがクラスthisポインターで呼び出されることを想定しているためです。

クラスからのデータが必要ない場合は、メソッドを静的にします。クラスからのデータが必要な場合は、userData パラメータでクラス ポインタを取得し、元のメソッドを呼び出す静的な「スタブ」を作成できます。何かのようなもの:

宣言:

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

意味

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

次に、関数を呼び出すときに次を使用します。

vrpnAnalog->register_change_handler( this, handle_analog_stub );

(ポインタへの static_cast に更新、感謝 rpavlik)

于 2014-04-22T00:13:10.347 に答える