I was writing an interface(using FLTK but this doesn't matter). I made a button and its callback function. In this callback function I need to use data in a variable outside the callback function(which is Myclass mc in the code). The code looks like the following (I didn't paste the unnecessary parts):
class Myclass
{
...
}
void button_callback( Fl_Widget* o, void* data)
{
Fl_Button* button=(Fl_Button*)o;
Myclass *a;
a=data;
a->MyMemberFunction();
}
int main()
{
Myclass mc;
...
Fl_Button button( 10, 150, 70, 30, "A button" );
button.callback( button_callback,&mc );
...
}
However at the place of "a=data;" I got an error saying void * cannot be assigned to Myclass *, what should I do?
Many thanks!
Assuming that the data coming in through the void* is a pointer to Myclass, you need to add a reinterpret_cast from the void*, like this:
Myclass *a = reinterpret_cast<Myclass*>(data);
This will tell the compiler that you know for sure that the data is a pointer to Myclass, letting you call MyMemberFunction() through that pointer.
you need to use any kind of type casting:
here is C variant:
Myclass *a = (Myclass*)data;
here is C++ variant:
Myclass* a = reinterpret_cast<Myclass*>(data);
Related
I'm trying to do something that seems like it should be fairly common but I've been unable to find anyone discussing it. this post on stackoverflow is similar to what I'm trying to do, but not quite the same.
I have an abstract base class:
#ifndef _ABASECLASS_H_
#define _ABASECLASS_H_
using namespace std;
#include <iostream>
#define CALL_MBR_FUNC(object, ptr_to_mem_func) ((object).*(ptr_to_mem_func))
class aBaseClass
{
public:
typedef void (aBaseClass::*aBaseClass_mem_func)();
int A;
int B;
aBaseClass();
aBaseClass(int a, int b);
virtual void function1(aBaseClass_mem_func infunc) = 0;
virtual void function2() = 0;
};
#endif /* _ACLASS_H_ */
and I have a derived class:
#ifndef _ASUBCLASS_H_
#define _ASUBCLASS_H_
using namespace std;
#include <iostream>
#include "aBaseClass.h"
/* A simple class containing two ints and some functions to demonstrate passing via various methods. It is a subclass of aClass*/
class aSubClass: public aBaseClass
{
public:
aSubClass();
aSubClass(int a, int b);
void function1(aBaseClass_mem_func infunc);
void function2(void);
};
#endif /* _ASUBCLASS_H_ */
where function1 and function2 are:
void aSubClass::function1(aBaseClass_mem_func infunc)
{
CALL_MBR_FUNC(*this, infunc)();
}
void aSubClass::function2(void)
{
A = 42;
B = 66;
}
Finally, in the main() I try to call function1 targeted on an object of type aSubClass, passing a pointer to function2 in aSubClass:
int main (int argc, const char * argv[])
{
aSubClass eh(2,5);
// This doesn't work
aBaseClass_mem_func trythis = &aSubClass::function2;
// This also doesn't work
eh.function1(&aSubClass::function2);
return(0);
}
OK, we can automatically cast a pointer-to-derived type to a pointer-to-base type. I have now read that we can't pass a pointer-to-derived-member-function to a pointer-to-base-member-function. I think I understand why (the derived member function might make use of things that exist in the derived class but don't exist in the base class).
But I'm trying to build a library of two categories of classes (derived from two base classes). Call them baseclass1 and baseclass2. One of the member functions in any derived class from baseclass1 needs to be able to be handed a particular member function from any derived class from baseclass2. Is there some trick I can use to carry out the necessary cast? Do I have to use the explicit keyword and define the cast somehow?
You could shorten this example a lot:
struct B {
virtual void foo() = 0;
};
struct D : B {
void foo() override { }
};
int main() {
void (B::*ptr)() = &D::foo; // error: cannot initialize a variable of
// type 'void (B::*)()' with an rvalue of type
// 'void (D::*)()': different classes ('B' vs 'D')
}
The error message, at least on clang, is pretty clear. gcc just says cannot initialize. The issue is just that you cannot implicitly convert a pointer-to-derived-member to a pointer-to-base-member. But you can do it explicitly with static_cast:
void (B::*ptr)() =
static_cast<void (B::*)()>(&D::foo); // ok!
Side-note: please remove the CALL_MBR_FUNC macro from your code and never write such a thing ever again.
Why it doesn't work:
One way you can think of a member function is this:
struct Foo {
void go () { }
} ;
Could also be expressed as:
void go ( Foo* this ) { }
So, this:
typedef void(Foo::*MemberFunctionPtr)() ;
Is kind of like this:
typedef void(*MemberFunctionPtrForFoo)(Foo*) ;
However, if you have a subclass like this:
struct Bar : public Foo {
void go2 () { }
} ;
That function is also kind of like this:
void go2 ( Bar* this ) { }
So when you take the address of Bar::go2, you're getting basically a pointer to a function that looks like void go2 ( Bar* this ). Why is this a problem?
Well let's look at what this means...
If you had this function:
void function ( Foo * this ) ;
And you were to do this:
Bar * bar = new Bar () ;
function ( bar ) ;
This would work (as it should). C++ kindly made it possible for you then to be able to do things like this:
void(*functionPtr)(Bar*) = &Foo::go ;
However, lets say you instead had this function:
void function ( Bar * this ) ;
And you did this:
Foo * foo = new Foo() ;
function ( foo ) ;
This wouldn't work because foo isn't [necessarily] a Bar. You could static_cast that, which is your way of telling the compiler "no, really, I'm pretty sure I know what I'm doing" (as opposed to reinterpret_cast, which is your way of telling the compiler "you're stupid; I know what I'm doing.")
Therefore, it also won't let you cast the member functions.
Another answer said that static_cast can convert the member functions, but that's only because static_cast is allowed to do the reverse of implicit cast (except for cv-qualification). You can do it, but it has the same caveats.
Disclaimer: this is a fairly simplified version of the spec, but it gets the point across.
A better solution in most cases:
On to a [potentially] better solution [unless absolute performance is key]: boost::function (or, as of C++11 std::function). This is a "functor".
Your member function could instead be written:
class Foo {
void function ( boost::function<void()> function ) { }
} ;
The functor object can be constructed with anything that can be called with the specified prototype (in this case, something taking no arguments and returning void). You can pass the address of a C-function for instance.
Another thing you can do is "bind" functions (which basically grabs arguments and makes a function). There's boost::bind for this.
For example you could do this:
Foo foo ;
Bar bar ;
foo.function ( boost::bind(&Bar::go2,&bar) ) ;
The boost bind takes some function as the first argument. If the function is a member function, the next argument must either be an instance of a class that the specified method can be called on (in which case it's copied) or a pointer to a class the specified method can be called on (in which case it's referenced). This example would actually cause the foo instance to call the bar instance (instead of itself), but you could pass &foo instead.
You can even be more creative:
class Foo {
void function ( boost::function<void(int)> function ) {
function ( 1 ) ;
}
void go2 ( int a , int b ) {
cout << a << " " << b << endl ;
}
} ;
Foo foo ;
foo.function ( boost::bind(&Foo::go2,&foo,_1,2) ) ;
That bind grabs:
The member-function-pointer for Foo::go2
A reference (or, 'pointer') to that instance of foo
A placeholder for "the first argument of the resultant function," which'll become the first argument in the call to go2
The number 2, which'll become the second argument in the call to go2
This is what'll be printed to the console:
1 2
This is an extraordinarily powerful tool and will lead you into the fantastic world of functional programming while making your life easier along the way. (It'll also make people like #CortAmmon hate you.)
I am trying to access the type of a userdata so that I can process it accordingly. Imagine I have a class named as Foo:
class Foo:public CObject
{
public:
Foo():CObject(){}
int type() {return 1;}
}
class CObject
{
public:
virtual int type(void)=0;
}
The rationale is that every class extending the CObject has a type that must be made known by an integer number (later on an enum). The class Foo is bind to lua using luaWwrapper (//https://bitbucket.org/alexames/luawrapper/src/fd9c4fdbf4b25034e3b8475a2c8da66b7caab427?at=default).
Foo* Foo_new(lua_State* L)
{
Foo* f=new Foo();
lua_newuserdata(L,sizeof(f));
std::cout<<"f="<<f;
return f;
}
In Lua user calls this as:
f=Foo.new()
print(f)
Now I have a C++ function, say print:
int lua_print(lua_State* L)
{
void *ud = luaL_checkudata(L, 1, "Foo"); //ud is not zero
std::cout<<"ud="<<ud;
CObject* obj=(CObject*)ud; //Casting to CObject
int objtype=obj->type(); //program CRASHES here
}
I have seen that the program crashes cause the memory addresses of Foo and ud are not the same. I assume ud refers to the memory of stack which contains the memory adress of Foo. How can I access stack's memory address or the preferred memory address of Foo?
You have to use placement new to initialize the object in the memory returned by lua_newuserdata.
Something in the lines of
void *ud = lua_newuserdata(L,sizeof(Foo));
new (ud) Foo();
Foo_new should just return the pointer to the object.
In other words, your Foo_new would look like this:
Foo* Foo_new(lua_State* L)
{
return new Foo();
}
However, if you have no special initialization you need to do, you don't even need to write this function. This function is supplied for you by magical templates if you don't write one yourself.
When you want to get your Foo object from the Lua state, you do this:
int lua_print(lua_State* L)
{
Foo *ud = luaW_to<Foo>(L, 1); //ud is not zero
std::cout<<"ud="<<ud;
CObject* obj=(CObject*)ud;
int objtype=obj->type();
}
If CObject is registered with LuaWrapper too, you don't even need to do the manual cast. You can just do luaW_to<CObject>(L, 1);
I need to pass something like a pointer that takes anything as a function parameter. You know, something without any predefined type or a type that can take anything like this:
void MyFunc( *pointer );
And then use it like:
char * x = "YAY!";
MyFunc(x);
int y = 10;
MyFunc(&y);
MyObj *b = new MyObj();
MyFunc(b);
And I don't want to use templates because I am mostly using C in my project.
Is there anything that can be used here except a function macro?
In C++, Boost.Any will let you do this in a type-safe way:
void func(boost::any const &x)
{
// any_cast a reference and it
// will throw if x is not an int.
int i = any_cast<int>(x);
// any_cast a pointer and it will
// return a null pointer if x is not an int.
int const *p = any_cast<int>(&x);
}
// pass in whatever you want.
func(123);
func("123");
In C, you would use a void pointer:
void func(void const *x)
{
// it's up to you to ensure x points to an int. if
// it's not, it might crash or it might silently appear
// to work. nothing is checked for you!
int i = *(int const*)x;
}
// pass in whatever you want.
int i = 123;
func(&i);
func("123");
You seem adverse to it but I'll recommend it anyway: if you're using C++, embrace it. Don't be afraid of templates. Things like Boost.Any and void pointers have a place in C++, but it is very small.
Update:
Well , I am making a small signals - slots - connections library to be
used with my gui toolkit. So that I can get rid of the Ugly WNDPROC. I
need these pointers for the connections.
If you need multi-target signals, Boost.Signals already provides a full and tested signals/slots implementation. You can use Boost.Bind (or std::bind, if you've got a C++0x compiler) to connect member functions:
struct button
{
boost::signal<void(button&)> on_click;
}
struct my_window
{
button b;
my_window()
{
b.on_click.connect(std::bind(&my_window::handle_click,
this, std::placeholders::_1));
}
void handle_click(button &b)
{
}
void simulate_click()
{
b.on_click(b);
}
};
If you only want a simple callback, Boost.Function (or std::function if you've got a C++0x compiler) will work well:
struct button
{
std::function<void(button&)> on_click;
}
struct my_window
{
button b;
my_window()
{
b.on_click = std::bind(&my_window::handle_click,
this, std::placeholders::_1);
}
void handle_click(button &b)
{
}
void simulate_click()
{
b.on_click(b);
}
};
You can use a function that takes a void*, but you must be aware of the pointer types that are not compatible with void*:
pointers to functions:
void MyFunc(void*);
MyFunc(&MyFunc); // WRONG
pointers to members:
void MyFunc(void*);
struct A { int x; };
MyFunc(&A::x); // WRONG
While these pointers are not compatible with void* (even with casting, on some compilers), they are themselves data. So you can pass a pointer to the pointer:
void MyFunc(void*);
void (*pfn)(void*) = &MyFunc;
MyFunc(&pfn); // ok
struct A { int x; };
int A::*px = &A::x;
MyFunc(&px); // ok
You can define the method as taking one void * argument. Of course, at that point, it's up to you to figure out what to do with the data (as far as accessing it or casting it.)
void MyFunc(void * ptr);
You could use:
void MyFunc( void* p){}
int g = 10;
MyFunc( (void*)&g );
void * is the way to do it. You can assign any pointer type to and from a void *. But to use the pointer in the called function, you'll have to know the type so you can create an appropriate local pointer or cast appropriately. You can encode a limited set of types as enum symbols, and perhaps use a switch to select type-specific behavior. But without a specific purpose or use-case, you might end up chasing your tail in a quest for generality for which C was never intended.
Another way would be to make a union to contain all the various types you know are needed.
typedef union {
int i;
char c;
float f;
} vartype;
Then if the value can carry around its own type-identifier, it becomes a tag-union or variant-record.
typedef struct {
enum type { INT, CHAR, FLOAT } type;
vartype var;
} varrec;
I'm having a hard time trying to make this work. I'm trying to execute a method
stocked in a method pointer tab.
here is my example :
void class1::fct1();
void Class1::fct2();
void Class1::manageFct()
{
static const void (*ptrFuncTab)[] = {
&Class1::fct1,
&Class1::fct2
};
opCode = 0;
ptrFunctab[opCode](); //==> call Cpu::fct1()
}
i understand that i have to put the instance in which i want to apply
the fct pointed. But how ?
Does anyone knows what i'm doing wrong ?
Thanks,
Cuva
Do this:
typedef void (Class1::*MemFn)();
static const MemFn ptrFuncTab[] = {
&Class1::fct1,
&Class1::fct2
};
What you were using is called pointer-to-function; what I'm using is called pointer-to-member-function. And they're not the same thing.
Use this function table as:
Class1 c;
(c.*ptrFuncTab[0])();
Or if you want to use pointer, then
Class1 *pC = new Class1();
(pC->*ptrFuncTab[0])();
Once you edit like Nawaz said, you call a function in the table like this:
Class1* ptr = new Class1();
(ptr->*ptrFuncTab[opCode])();
for a pointer, and like this:
Class1 ref;
(ref.*ptrFuncTab[opCode])();
for a reference.
maybe this is the continuation of this thread,
The program compiles without errors or warnings but when I run it, and the handler function is called, I get EXEC_BAD_ADDRESS
void MainController::show_color_trackbars(int *h, int *s, int *v){
String winName = "HSV Trackbars";
namedWindow(winName, CV_WINDOW_AUTOSIZE);
std::map<String, void*> user_data_h;
user_data_h["Object"] = this; //this is a MainController object
user_data_h["h"] = h;
createTrackbar("trackbar_H", winName, h, 255, trackbar_handler, &user_data_h);
};
void trackbar_handler(int value, void *user_data){//callback for the track bar
std::map <String, void*> *user_data_map;
user_data_map = reinterpret_cast<std::map<String, void *> *>(user_data);
MainController *controller;
controller = reinterpret_cast<MainController *>((*user_data_map)["Object"]);
int *var;
var = reinterpret_cast<int*> ((*user_data_map)["h"]);
//do something with controller and var
};
I am mistaking something when casting? I cannot think of another reason this code is failing.
Thanks in advance
That's because in all probablity user_data_h is a local variable and is already destroyed when trackbar_handler is called. trackbar_handler works on a pointer which is no longer valid!
Please check if it is okay to have user_data_h dynamically allocated and register that pointer with the callback dispatch.