Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

[Tobii Eye Tracking] stuck at "non-standard syntax; use '&' to create a pointer to member"



  • Hello,
    I have a Tobii Eye Tracking device and experimented with it.
    Now I'd like to get the focus point's coordinates. In order to achieve this I followed this documentation: https://tobii.github.io/stream_engine/#tobii_gaze_point_subscribe
    Well, it works in a Visual Studio Console Application project. But it does not in Qt even the code pretty much is identical.

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <C:/Qt/consumer_stream_engine_windows_2.2.1.3001/include/tobii/tobii.h>
    //#include <C:/Qt/consumer_stream_engine_windows_2.2.1.3001/include/tobii/tobii_engine.h>
    #include <C:/Qt/consumer_stream_engine_windows_2.2.1.3001/include/tobii/tobii_streams.h>
    //#include <C:/Qt/consumer_stream_engine_windows_2.2.1.3001/include/tobii/tobii_wearable.h>
    #pragma comment(lib, "C:/Qt/consumer_stream_engine_windows_2.2.1.3001/lib/x64/tobii_stream_engine.lib")
    
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    private slots:
        void on_pushButton_clicked();
    
    private:
        Ui::MainWindow *ui;
        tobii_api_t* api;
        tobii_error_t error = tobii_api_create( &api, NULL, NULL);
        static void url_receiver(char const* url, void* user_data);
        char print_coords = 'n';
        void gaze_point_callback(tobii_gaze_point_t const* gaze_point, void* user_data);
        tobii_error_t tobii_gaze_point_subscribe( tobii_device_t* device, tobii_gaze_point_callback_t callback, void* user_data );
    };
    
    #endif // MAINWINDOW_H
    
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    
    tobii_gaze_point_t const* gaze_point = Q_NULLPTR;
    
    void MainWindow::gaze_point_callback(tobii_gaze_point_t const* gaze_point, void* user_data)
    {
        if (gaze_point->validity == TOBII_VALIDITY_VALID)
        {
            if (gaze_point->position_xy[0] <= 0.5)
            {
                ui->plainTextEdit->appendPlainText("links ");
            }
            else
            {
                ui->plainTextEdit->appendPlainText("rechts ");
            }
    
            if (gaze_point->position_xy[1] <= 0.5)
            {
                ui->plainTextEdit->appendPlainText("oben \n");
            }
            else
            {
                ui->plainTextEdit->appendPlainText("unten \n");
            }
    
            //if (print_coords == 'j')
            {
                //cout << endl << gaze_point->position_xy[0] << " --- " << gaze_point->position_xy[1];
            }
    
        }
    }
    
    void MainWindow::url_receiver(char const* url, void* user_data)
    {
        char* buffer = (char*)user_data;
        if (*buffer != '\0')
        {
            return; // only keep first value
        }
    
        if (strlen(url) < 256)
        {
            strcpy(buffer, url);
        }
    }
    
    
    //tobi_api
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::on_pushButton_clicked()
    {
    
        tobii_api_t* api;
        tobii_error_t error = tobii_api_create(&api, NULL, NULL);
    
        assert(error == TOBII_ERROR_NO_ERROR);
    
        char url[256] = { 0 };
        error = tobii_enumerate_local_device_urls(api, url_receiver, url);
        assert(error == TOBII_ERROR_NO_ERROR && *url != '\0');
    
        tobii_device_t* device;
        error = tobii_device_create(api, url, &device);
        assert(error == TOBII_ERROR_NO_ERROR);
    
        error = tobii_gaze_point_subscribe(device, gaze_point_callback, 0); // error occurs here
        assert(error == TOBII_ERROR_NO_ERROR);
    
        //int is_running = 10; // in this sample, exit after some iterations
        for (int is_running = 10; is_running > 0; is_running--)
        {
            error = tobii_wait_for_callbacks(NULL, 1, &device);
            assert(error == TOBII_ERROR_NO_ERROR || error == TOBII_ERROR_TIMED_OUT);
    
            error = tobii_device_process_callbacks(device);
            assert(error == TOBII_ERROR_NO_ERROR);
        }
    
        error = tobii_gaze_point_unsubscribe(device);
        assert(error == TOBII_ERROR_NO_ERROR);
    
        error = tobii_device_destroy(device);
        assert(error == TOBII_ERROR_NO_ERROR);
    
        error = tobii_api_destroy(api);
        assert(error == TOBII_ERROR_NO_ERROR);
    }
    

    Any idea? Thanks


  • Lifetime Qt Champion

    Hi,

    Can you show where exactly you got that error ?



  • @SGaist ah sorry, forgot to comment that. I added a comment at the line the error occurs. It's right above the for loop.

        error = tobii_gaze_point_subscribe(device, gaze_point_callback, 0); // error occurs here
        assert(error == TOBII_ERROR_NO_ERROR);
    


  • @SnuggleKat
    Generally, if you are going to use a member function as a callback, it has to be static.
    Which creates the problem of member access. Since most callback APIs let you define a variable to pass as a void *, you should pass in "this" then cast to the appropriate object type.


  • Lifetime Qt Champion

    Hi
    As @mranger90 says, it expects a free function. A global function like the sample shows.
    That means it has to be declared static with the rules that follow that for class members.

    So if possible to change the code at the "other end" to cast to your type, it would
    work fine.

    If that is not possible, you are stuck using a normal function.

    UPDATE:
    ahh, i looked at the sample
    https://tobii.github.io/stream_engine/#tobii_gaze_point_subscribe

    Seems you can just use the cast way as @mranger90 says :)



  • Thank you. I put it into a global function.
    But now I get this error:
    mainwindow.obj:-1: Fehler: LNK2019: unresolved external symbol "private: void __cdecl MainWindow::asdf(void)" (?asdf@MainWindow@@AEAAXXZ) referenced in function "private: void __cdecl MainWindow::on_pushButton_clicked(void)" (?on_pushButton_clicked@MainWindow@@AEAAXXZ)


  • Lifetime Qt Champion

    Did you make an asdf function?
    show more code or its impossible to guess :)



  • @SnuggleKat said in [Tobii Eye Tracking] stuck at "non-standard syntax; use '&' to create a pointer to member":

    void gaze_point_callback(tobii_gaze_point_t const* gaze_point, void* user_data);

    头文件 里 修改为
    static void gaze_point_callback(tobii_gaze_point_t const* gaze_point, void* user_data);


Log in to reply