-1

I am new to C/C++. Currently, I am working on a project in which a haptic device is used. I just want to return a value when the device button is pressed below is my code.

#ifdef  _WIN64
#pragma warning (disable:4996)
#endif

#include <stdio.h>
#include <assert.h>

#if defined(WIN32)
# include <conio.h>
#else
# include "conio.h"
#endif

#include <HD/hd.h>
#include <HL/hl.h>

#include <HDU/hduError.h>

int HLCALLBACK buttonCB(HLenum event, HLuint object, HLenum thread, 
                       HLcache *cache, void *userdata);

/*******************************************************************************
 Main function.
*******************************************************************************/
int btn;
int main(int argc, char *argv[])
{
    HHD hHD;
    HHLRC hHLRC;
    HDErrorInfo error;
    HLerror frameError;

    hHD = hdInitDevice(HD_DEFAULT_DEVICE);
    if (HD_DEVICE_ERROR(error = hdGetError())) 
    {
        hduPrintError(stderr, &error, "Failed to initialize haptic device");
        fprintf(stderr, "\nPress any key to quit.\n");
        getch();
        return -1;
    }
    hdMakeCurrentDevice(hHD);    
    hHLRC = hlCreateContext(hHD);
    hlMakeCurrent(hHLRC);

    /* Add a callback to handle button down in the collision thread. */
    hlAddEventCallback(HL_EVENT_1BUTTONDOWN, HL_OBJECT_ANY, HL_CLIENT_THREAD, 
                       buttonCB, 0);
    hlAddEventCallback(HL_EVENT_2BUTTONDOWN, HL_OBJECT_ANY, HL_CLIENT_THREAD, 
                       buttonCB, 0);

    printf("Move around to feel the ambient stick-slip friction.\n\n");
    printf("Press and hold the primary stylus button to feel the spring effect.\n\n");
    printf("Press the second stylus button to trigger an impulse.\n\n");

    /* Run the main loop. */
    while (!_kbhit())
    {
        hlCheckEvents();
        Sleep(3000);

    }
    hlDeleteContext(hHLRC);
    hdDisableDevice(hHD);

    return 0;
}

void HLCALLBACK buttonCB(HLenum event, HLuint object, HLenum thread, 
                         HLcache *cache, void *userdata)
{
    int btn;
    if (event == HL_EVENT_1BUTTONDOWN)
    {
        btn = 1;
        printf("Button 1 pressed %d ", btn);
        return btn;
    }
    else if (event == HL_EVENT_2BUTTONDOWN)
    {
        btn = 2;
        printf("Button 2 pressed %d ", btn);
        return btn;

    }
}

/******************************************************************************/

The buttonCB callback function is used as an event. These button events is checked in main loop using this command hlCheckEvents();. In code you can see the int HLCALLBACK buttonCB function that trigger an event when the button is pressed. I want that when the button is pressed, the event should store a value in a variable called btn that can be accessed from the main function. Please help me out with how I do this.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • 2
    Its okay that you are new to both `C` and `C++`, but for which language would you like an answer? It appears you are writing in `C`. The `void *userdata` argument is what can be used here. In general, `void *` is able to convey any type. – ryyker Jan 31 '22 at 13:08
  • Hey, @ryyker I need the answer in C language. How to use 'void *'. Can I get an example or make some changes in my code if possible. Thanks – suleman Ali kazmi Jan 31 '22 at 13:18
  • Based on general experience, not looking up the documentation for setting a callback this way, the `void *userdata` parameter is intended to serve this purpose. It provides a pointer to memory where the callback routine may read or write data. Looking at your hlAddEventCallback` call, I suspect the argument you currently pass as `0` is supposed to be that address. Instead of passing `0`, you could pass `&btn`. Inside `buttonCB`, you would convert this address to the desired type and use it. E.g., if `btn` is an `int`, then `* (int *) userdata = 3;` would set `btn` to 3. – Eric Postpischil Jan 31 '22 at 13:24
  • There is an example [here](https://stackoverflow.com/a/60427456/645128) that matches what you have described. In your function you are using `return` statements, but your function is typed as `void` . The example uses a prototype returning `int`. – ryyker Jan 31 '22 at 13:33

2 Answers2

2

You might use userData to transfer data, for example something like:

int button = 0; // Should be valid as long as event might be called.

/* Add a callback to handle button down in the collision thread. */
hlAddEventCallback(HL_EVENT_1BUTTONDOWN, HL_OBJECT_ANY, HL_CLIENT_THREAD, 
                   buttonCB, &button);
hlAddEventCallback(HL_EVENT_2BUTTONDOWN, HL_OBJECT_ANY, HL_CLIENT_THREAD, 
                   buttonCB, &button);
// ..

/* Run the main loop. */
while (!_kbhit())
{
    // button = 0; // Potentially reinit here
    hlCheckEvents();
    printf("button value: %d", button); // Do work with last value
    Sleep(3000);
}

and then your callback

void HLCALLBACK buttonCB(HLenum event, HLuint object, HLenum thread, 
                         HLcache *cache, void *userdata)
{
    int* button = (int*) userdata;
    if (event == HL_EVENT_1BUTTONDOWN)
    {
        *button = 1;
        printf("Button 1 pressed %d ", btn);
    }
    else if (event == HL_EVENT_2BUTTONDOWN)
    {
        *button = 1; = 2;
        printf("Button 2 pressed %d ", btn);
    }
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
-3

I am not really into event handling. But I'll try to help.

You are returning btn from the function, which is of the type int, but the function return type is void, which means the function cannot return anything. So, the fix is simple. Change the return type of the buttonCB function from void to int:

/*void*/ int HLCALLBACK buttonCB(HLenum event, HLuint object, HLenum thread, 
                         HLcache *cache, void *userdata)
{
    int btn;
    if (event == HL_EVENT_1BUTTONDOWN)
    {
        btn = 1;
        printf("Button 1 pressed %d ", btn);
        return btn;
    }
    else if (event == HL_EVENT_2BUTTONDOWN)
    {
        btn = 2;
        printf("Button 2 pressed %d ", btn);
        return btn;

    }
}

Now the return type of the function is int, that is the type of your btn variable that you're returning.

The Coding Fox
  • 1,488
  • 1
  • 4
  • 18
  • That callback have fixed signature (from `hlAddEventCallback`) that cannot be changed. – Jarod42 Jan 31 '22 at 13:26
  • Oh ok. As I mentioned I am not experienced in event handling. – The Coding Fox Jan 31 '22 at 13:37
  • @SolvedGames so why do you answer the question if you do not know the answer? – 0___________ Jan 31 '22 at 13:38
  • I thought this might be what he needed. – The Coding Fox Jan 31 '22 at 14:04
  • Changing the return type of your function has a few effects: a) It does no longer match the mandatory function type for registering the callback. b) No one will care about the returned value because this function is not supposed to return anything. => That violate the API and doesn't get any benefit for you. – Gerhardh Jan 31 '22 at 16:16