Casting C++ class into another one to create OpenCV trackbar handle - c++

To not mess around with global variables and functions, I'd like to use a function of a class as a function for a trackbar handle in OpenCV. Following code illustrates the idea:
void cam::set_Trackbarhandler(int i, void *func)
{
/* This function might be called whenever a trackbar position is changed */
}
void cam::create_Trackbars(void)
{
/**
* create trackbars and insert them into main window.
* 3 parameters are:
* the address of the variable that is changing when the trackbar is moved,
* the maximum value the trackbar can move,
* and the function that is called whenever the trackbar is moved
*/
const string trck_name = "Exposure";
char wnd_name[128];
get_Mainwindowname(wnd_name, sizeof(wnd_name));
createTrackbar(trck_name, //Name of the trackbar
wnd_name, //Name of the parent window
&setting, //value that's changed
(int)out_max, //maximum value
this->set_Trackbarhandler); //pointer to the function that's called
}
I hope that outlines it. The error I get when compiling reads
error: cannot convert 'cam::set_Trackbarhandler' from type 'void (cam::)(int, void*)' to type 'cv::TrackbarCallback {aka void (*)(int, void*)}'|
Is there a way to cast void (cam::)(int, void*) into a simple void (*)(int, void*) or do I have to use a global function, that is
void set_Trackbarhandler(int i, void *func)
? If I have to do it like that, my last resort is to use the void pointer (see http://docs.opencv.org/modules/highgui/doc/user_interface.html) and send a pointer to the class back in, as
createTrackbar(trck_name,
wnd_name,
&setting,
(int)out_max,
set_Trackbarhandler, //now a global function
this);
I guess. In the set_Trackbarhandler function I'd make a cast like
cam *ptr = static_cast<cam *>(func);
Sounds a bit complicated, though.

well. you need some indirection, but it's not that bad...
class cam
{
public:
void myhandler(int value)
{
// real work here, can use 'this'
}
static void onTrack(int value, void* ptr)
{
cam* c = (cam*)(ptr);
c->myhandler(value);
}
};
createTrackbar(trck_name,
wnd_name,
&setting,
(int)out_max,
cam::onTrack, //now a static member
this);

Related

problem of using const when passing a pointer

Visual studio shows a error saying "the object has type quantifiers that are not compatible with the member function 'somfunc' "
class T_ship {
public:
...
float ship_run(int ship_len);
// function ship_run doesn't change any class member values
};
There is a function in main() with *T_ship pointer passed as input.
void draw_ship(const T_ship * a_shp){
float dist = a_ship-> ship_run(100);
// there is a red wavy line under a_ship
}
Many thanks if someone can help.
If you want the actual pointer to be const and not the object pointed to, put the const in front of the type, so like this:
T_ship * const
However in your case if the function ship_run doesn't modify anything you should
mark it as const at the end of the function as well so like this:
float ship_run(int v) const { /* your code here */ }

What does this callback function do?

So I started to develope an OpenCV program and the thing is that I don't know what this segment of code do in the whole context. Below is an abstract version of the whole code.
class foo{
private:
friend void callBack(void *param);
void draw(void);
public:
void func(void);
void update(void);
}
void callBack(void *param){
foo *context = static_cast<foo*>(param);
if(context){
context->draw();
}
}
foo::foo(std::string windowName){
cv::namedWindow(windowName, frameSize.width, frameSize.height);
cv::resizeWindow(windowName, frameSize.width, frameSize.height);
cv::setOpenGlContext(windowName);
cv::setOpenGlDrawCallback(windowName, callBack, this);
}
void foo::func(void){
cv::updateWindow(m_windowName);
}
void draw(void){
//implementation shows here!!
}
You don't have to explain all the code here. All I need to know is the part where static casting happens. What does it do? Why does a person who implements the code write it this way?
As you can see from the documentation of cv::setOpenGlDrawCallback
The signature is:
void cv::setOpenGlDrawCallback(const String& winname,
OpenGlDrawCallback onOpenGlDraw,
void* userdata = 0
)
The OpenGLDrawCallback is a function pointer of type void (void* arg): where arg is any pointer type you pass to it. In this case, OpenCV actually passes userdata to it. See How do function pointers in C work? (still applicable to C++)
cv::setOpenGlDrawCallback(windowName, callBack, this);
In your code, passing this implicitly converted (a copy of the pointer) it to void* and held by userdata . And and callback is called to draw on your frame
All I need to know is the part where static casting happens. What does
it do? Why does a person who implements the code write it this way?
void callBack(void *param){
foo *context = static_cast<foo*>(param);
if(context){
context->draw();
}
}
The casting converts the void pointer, param to an object of type foo. it basically gets back the semantics of this that was casted when you passed it as a void pointer.

Function parameter: Pointer to array of objects

In my main function I create an array of objects of a certain class "Menu"
And when I call a function I want to provide a pointer to that array.
Menu menu[2];
// Create menu [0], [1]
Function(POINTER_TO_ARRAY);
Question: What is the correct way to write the Function parameters?
I try:
Function(&menu);
and in Header file:
void Function(Menu *menu[]); // not working
error: Cannot convert parameter 1 from Menu(*)[2] to Menu *[]
void Function(Menu * menu); // not working
error: Cannot convert parameter 1 from Menu(*)[2] to Menu *[]
and I can't come up with any other way to do this and I can't find a solution to this particular problem.
Simply, I want to be able to access the Menu array within the function through a pointer. What are the difference in normal pointer to a pointer to an array?
Declaration:
void Function(Menu* a_menus); // Arrays decay to pointers.
Invocation:
Function(menu);
However, you would need to inform Function() how many entries are in the array. As this is C++ suggest using std::array or std::vector which have knowledge of their size, beginning and end:
std::vector<Menu> menus;
menus.push_back(Menu("1"));
menus.push_back(Menu("2"));
Function(menus);
void Function(const std::vector<Menu>& a_menus)
{
std::for_each(a_menus.begin(),
a_menus.end(),
[](const Menu& a_menu)
{
// Use a_menu
});
}
Either by const or non-const pointer
void Function(Menu const* menu);
void Function(Menu* menu);
...or by const or non-const reference
void Function(Menu const (&menu)[2]);
void Function(Menu (&menu)[2]);
which can be generalized to a template so that the array size will be deduced by the compiler:
template<size_t N> void Function(Menu const (&menu)[N]);
template<size_t N> void Function(Menu (&menu)[N]);
Always call as Function(menu);
Should work if you use
void Function(Menu * menu);
and call using
Function(menu);
instead of
Function(&menu);
passing the array name causes it to decay to a pointer to the type contained in the array. However, as #hmjd says in his answer you will also need to pass the array size, so his suggestion of using a vector is favourable if this option is open to you.
You can use
Function((void *) whatever_pointer_type_or_array_of_classes);
in your main.
And in the function:
type Function(void * whatever)
{
your_type * x =(your_type *) whatever;
//use x
....
x->file_open=true;
....
}

Callback to a non-static C++ Member Function

I would like someone to shed some light this code snippet, which confuses me.
//-------------------------------------------------------------------------------
// 3.5 Example B: Callback to member function using a global variable
// Task: The function 'DoItB' does something that implies a callback to
// the member function 'Display'. Therefore the wrapper-function
// 'Wrapper_To_Call_Display is used.
#include <iostream.h> // due to: cout
void* pt2Object; // global variable which points to an arbitrary object
class TClassB
{
public:
void Display(const char* text) { cout << text << endl; };
static void Wrapper_To_Call_Display(char* text);
/* more of TClassB */
};
// static wrapper-function to be able to callback the member function Display()
void TClassB::Wrapper_To_Call_Display(char* string)
{
// explicitly cast global variable <pt2Object> to a pointer to TClassB
// warning: <pt2Object> MUST point to an appropriate object!
TClassB* mySelf = (TClassB*) pt2Object;
// call member
mySelf->Display(string);
}
// function does something that implies a callback
// note: of course this function can also be a member function
void DoItB(void (*pt2Function)(char* text))
{
/* do something */
pt2Function("hi, i'm calling back using a global ;-)"); // make callback
}
// execute example code
void Callback_Using_Global()
{
// 1. instantiate object of TClassB
TClassB objB;
// 2. assign global variable which is used in the static wrapper function
// important: never forget to do this!!
pt2Object = (void*) &objB;
// 3. call 'DoItB' for <objB>
DoItB(TClassB::Wrapper_To_Call_Display);
}
Question 1: Regarding this function call:
DoItB(TClassB::Wrapper_To_Call_Display)
Why does Wrapper_To_Call_Display not take any arguments, although it is supposed to take a char* argument according to its declaration?
Question 2: DoItB is declared as
void DoItB(void (*pt2Function)(char* text))
What I’ve understood so far is that DoItB takes a function pointer as argument, but why does the function call DoItB(TClassB::Wrapper_To_Call_Display) take TClassB::Wrapper_To_Call_Display as argument even tough it’s not a pointer?
Thanx in advance
Source of code snippet: http://www.newty.de/fpt/callback.html
In C/C++ when a function name is used with no parameters - that is no parenthesis - it is a pointer to a function. So TClassB::Wrapper_To_Call_Display is a pointer to the address in memory where the code for the function is implemented.
Since TClassB::Wrapper_To_Call_Display is a pointer to a void function that takes a single char* it's time is void (*)(char* test) so it matches the type required by DoItB.

Callback to non-static method

Think of your basic GLUT programs. They simply run from a main method and contain callbacks like `glutMouseFunc(MouseButton) where MouseButton is the name of a method.
What I have done is I have encapsulated the main file into a class, so that MouseButton is no longer a static function but has an instance. But doing this gives me a compilation error :
Error 2 error C3867: 'StartHand::MouseButton': function call missing argument list; use '&StartHand::MouseButton' to create a pointer to member c:\users\angeleyes\documents\visual studio 2008\projects\capstone ver 4\starthand.cpp 388 IK Engine
It is not possible to provide a code sample as the class is quite huge.
I have tried using this->MouseButton but that gives the same error. Can't a pointer to an instance function be given for callback?
As the error message says, you must use &StartHand::MouseButton syntax to get a pointer to a member function (ptmf); this is simply mandated as part of the language.
When using a ptmf, the function you are calling, glutMouseFunc in this case, must also expect to get a ptmf as a callback, otherwise using your non-static MouseButton won't work. Instead, a common technique is for callbacks to work with a user-supplied void* context, which can be the instance pointer—but the library doing the callbacks must explicitly allow this parameter. It's also important to make sure you match the ABI expected by the external library (the handle_mouse function below).
Since glut doesn't allow user-supplied context, you have to use another mechanism: associate your objects with glut's current window. It does provide a way to get the "current window", however, and I've used this to associate a void* with the window. Then you simply need to create a trampoline to do the type conversion and call the method.
Machinery:
#include <map>
int glutGetWindow() { return 0; } // make this example compile and run ##E##
typedef std::pair<void*, void (*)(void*,int,int,int,int)> MouseCallback;
typedef std::map<int, MouseCallback> MouseCallbacks;
MouseCallbacks mouse_callbacks;
extern "C" void handle_mouse(int button, int state, int x, int y) {
MouseCallbacks::iterator i = mouse_callbacks.find(glutGetWindow());
if (i != mouse_callbacks.end()) { // should always be true, but possibly not
// if deregistering and events arrive
i->second.second(i->second.first, button, state, x, y);
}
}
void set_mousefunc(
MouseCallback::first_type obj,
MouseCallback::second_type f
) {
assert(obj); // preconditions
assert(f);
mouse_callbacks[glutGetWindow()] = MouseCallback(obj, f);
//glutMouseFunc(handle_mouse); // uncomment in non-example ##E##
handle_mouse(0, 0, 0, 0); // pretend it's triggered immediately ##E##
}
void unset_mousefunc() {
MouseCallbacks::iterator i = mouse_callbacks.find(glutGetWindow());
if (i != mouse_callbacks.end()) {
mouse_callbacks.erase(i);
//glutMouseFunc(0); // uncomment in non-example ##E##
}
}
Example:
#include <iostream>
struct Example {
void MouseButton(int button, int state, int x, int y) {
std::cout << "callback\n";
}
static void MouseButtonCallback(
void* self, int button, int state, int x, int y
) {
static_cast<Example*>(self)->MouseButton(button, state, x, y);
}
};
int main() {
Example obj;
set_mousefunc(&obj, &Example::MouseButtonCallback);
return 0;
}
Notice that you don't call glutMouseFunc directly anymore; it is managed as part of [un]set_mousefunc.
Just in case it isn't clear: I've rewritten this answer so it should work for you and so that it avoids the C/C++ linkage issue being debated. It will compile and run as-is (without glut), and it should work with glut with only minor modification: comment or uncomment the 4 lines marked ##E##.
No, a pointer to an instance function can not be given to a callback function expecting a function pointer of a certain signature. Their signatures are different. It won't compile.
Generally such APIs allow you to pass in a void* as a "context" parameter. You pass in your object there, and write a wrapper function which takes the context as the callback. The wrapper casts it back to whatever class you were using, and calls the appropriate member function.
You can't replace a static callback with an instance one. When the caller calls your callback, on what instance whoul it call? In other words, how does the caller pass in the formal 'this' argument?
The solution is to have a static callback stub and pass the instance as argument, which implies the callee must accept an arbitrary pvoid that will pass back when invoking the callback. In the stub, you can then call the non-static method:
class C {
void f() {...}
static void F(void* p) {
C* pC = (C*)p;
pC->f();
}
}
C* pC = ...;
someComponent.setCallback(&C::F, pC);
Contrary to what everyone seems to be saying, you most definitely CAN use a non-static member function as a callback method. It requires special syntax designed specifically for getting pointers to non-static members, and special syntax to call that function on a specific instance of a class. See here for a discussion of the needed syntax.
Here is sample code that illustrates how this works:
#include <cstdlib>
#include <string>
#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
using namespace std;
class Operational
{
public:
Operational(int value) : value_(value) {};
string FormatValue() const ;
private:
int value_;
};
string Operational::FormatValue() const
{
stringstream ss;
ss << "My value is " << value_;
return ss.str();
}
typedef string(Operational::*FormatFn)() const; // note the funky syntax
Operational make_oper(int val)
{
return Operational(val);
}
int main()
{
// build the list of objects with the instance callbacks we want to call
Operational ops[] = {1, 2, 3, 5, 8, 13};
size_t numOps = sizeof(ops)/sizeof(ops[0]);
// now call the instance callbacks
for( size_t i = 0; i < numOps; ++i )
{
// get the function pointer
FormatFn fn = &Operational::FormatValue;
// get a pointer to the instance
Operational* op = &ops[i];
// call the callback on the instance
string retval = (op->*fn)();
// display the output
cout << "The object # " << hex << (void*)op << " said: '" << retval << "'" << endl;
}
return 0;
}
The output of this program when I ran it on my machine was:
The object # 0017F938 said: 'My value is 1'
The object # 0017F93C said: 'My value is 2'
The object # 0017F940 said: 'My value is 3'
The object # 0017F944 said: 'My value is 5'
The object # 0017F948 said: 'My value is 8'
The object # 0017F94C said: 'My value is 13'
You cannot use a non-static member function in this case.
Basically the type of the argument expected by glutMouseFunc is
void (*)(int, int, int, int)
while the type of your non-static member function is
void (StartHand::*)(int, int, int, int)
First problem is that types don't really match.
Second, in order to be able to call that method, the callback would have to know which object ( i.e. "this" pointer ) your method belongs to ( that's pretty much why the types are different in the first place ).
And third, I think you're using the wrong syntax to retrieve the method's pointer. The right syntax should be: &StartHand::MouseButton.
So, you have to either make that method static or use some other static method that would know which StartHand pointer to use to call MouseButton.
The following works in c++ to define a c callback function, useful for example when using glut (glutDisplayFunc, glutKeyboardFunc, glutMouseFunc ...) when you only need a single instance of this class :
MyClass * ptr_global_instance = NULL;
extern "C" void mouse_buttons_callback(int button, int state, int x, int y) {
// c function call which calls your c++ class method
ptr_global_instance->mouse_buttons_cb(button, state, x, y);
}
void MyClass::mouse_buttons_cb(int button, int state, int x, int y) {
// this is actual body of callback - ie. if (button == GLUT_LEFT_BUTTON) ...
// implemented as a c++ method
}
void MyClass::setup_glut(int argc, char** argv) { // largely boilerplate glut setup
glutInit(&argc, argv);
// ... the usual suspects go here like glutInitWindowSize(900, 800); ...
setupMouseButtonCallback(); // <-- custom linkage of c++ to cb
// ... other glut setup calls here
}
void MyClass::setupMouseButtonCallback() {
// c++ method which registers c function callback
::ptr_global_instance = this;
::glutMouseFunc(::mouse_buttons_callback);
}
In your MyClass header we add :
void mouse_buttons_cb(int button, int state, int x, int y);
void setupMouseButtonCallback();
This also works using identical logic flows to setup your glut
call to glutDisplayFunc(display)