Question

Currently I have a number of sliders that are used to change image values. I am using the OpenCV track bar for the slider which has a callback to a different function for each of my sliders. I would like to have my sliders callback point to a single callback function and then use the user data to identify which track bar made the call.

Here is the documentation for the track bar

I am unsure what values i should be passing to void*, and also how to then retrieve this value form my callback function Below is an example of my track bar which compiles.

int ref = 1;
createTrackbar("Name","Window",0, 1, myFunc, &ref);

In my callback function I try and retrieve the value of ref.

void myFunc(int value, void *userdata)
{
    int val = *((int*)&userdata);
    cout << val << endl;
}

I had issues trying to convert the pointer back to an int, this is a solution i found online which gives me val as the address of ref.

int val = *((int*)&userdata);

This seems a lot of hassle, as i then have to get the value back form the address at val. Is there an easier way to do this?

Was it helpful?

Solution

No, there is no simplier way. It's nessesary minimum for functionality you want.

OTHER TIPS

Passing a single variable which seems less hassle.

void cb_func(..., void *userdata) {
    int val = *static_cast<int *>(userdata);
}

Call it with:

cv_function_takes_callback(..., cb_func, static_cast<void *>(&val));

C++11 way of passing multiple variables.
You can pass references and even lambda functions.

type1 var1;
type2 var2;
auto lambda_no_capture = [](...) { ... };

typedef std::tuple<type1, const type2 &, decltype(lambda_no_capture)> tup_t;
tup_t tup(var1, var2, lambda_no_capture);

auto cb_func = [](..., void *userdata) -> void {
    tup_t &tup = *static_cast<tup_t *>(userdata);
    type1 var1 = std::get<0>(tup);
    decltype(auto) var2 = std::get<const type2 &>(tup); // requires c++14
    auto lambda_no_capture = std::get<2>(tup);
};

cv_function_takes_callback(..., cb_func, static_cast<void *>(&tup));

A few notes:

  • You can use auto var1 = std::get<0>(tup); but being explicit is better.

  • In case you are using auto with referenced variables, use const auto &var2 = std::get<1>(tup);. If you are not bound to C++11, decltype(auto) is what this is for.

  • Passing lambda functions to the callback functions seems cool but it is no different from using functions at global scope since they cannot have captured parameters.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top