-
wrote on 21 Sept 2016, 19:02 last edited by kshegunov
Hi, this is my first post in this forum, so i am not sure General and Desktop is the right place for it.
Let me know, if it will be moved.I am working on an application that uses a 3D engine. The engine has a C sdk, so until now everything went well, more or less.
Now i would like to use a statement of the engine that requires a function pointer as a parameter casted to void *. Like this in MyClass.cpp:MyClass::constructor() { ... } MyClass::do_this() { ... create_someth(par1, par2, (void *) function ptr, par4); ... }
I had a function, also in this class, for passing like this:
void myFunc(int p1, long p2) { first_line; second_line; }
In the header of my class there is definition of my function:
... public: ... void myFunc(int, long); ...
So, how should look like the proper function pointer passing in this line:
create_someth(par1, par2, (void *) function ptr, par4);
Thanks in advance.
-
Hi, this is my first post in this forum, so i am not sure General and Desktop is the right place for it.
Let me know, if it will be moved.I am working on an application that uses a 3D engine. The engine has a C sdk, so until now everything went well, more or less.
Now i would like to use a statement of the engine that requires a function pointer as a parameter casted to void *. Like this in MyClass.cpp:MyClass::constructor() { ... } MyClass::do_this() { ... create_someth(par1, par2, (void *) function ptr, par4); ... }
I had a function, also in this class, for passing like this:
void myFunc(int p1, long p2) { first_line; second_line; }
In the header of my class there is definition of my function:
... public: ... void myFunc(int, long); ...
So, how should look like the proper function pointer passing in this line:
create_someth(par1, par2, (void *) function ptr, par4);
Thanks in advance.
A function pointer is the address to the function in the .text part of the binary. Global functions and class static functions are exactly the same, because they don't carry the
this
pointer. They can be passed directly as callbacks. Whereas class methods and virtual methods can't they need to be bound to an object. The address of the function (as anything in C++) is given by its name, quite literally:class MyClass { public: static int someFunction(char * param1, int param2); } typedef int (*FunctionType)(char *, int); //< We call the pointer to function type FunctionType (the line is optional and for simplicity). FunctionType pointerToFunction = &MyClass::someFunction; //< Literally means get the address of MyClass::someFunction and save it in the pointerToFunction variable.
To finish up anything that's of pointer type can be implicitly converted to
void *
, so you can use:create_someth(par1, par2, &MyClass::someFunction, par4);
directly.
-
wrote on 21 Sept 2016, 19:44 last edited by
Thanks for the really quick reply. It is great!
Unfortunately, it don't want to work. I have got the following message:
cannot convert 'void (MyClass::)(int, long)' to 'FunctionType {aka int ()(int, long)}' in initializationI thought maybe the type of the typedef wrong so i changed that from int to void. It is a bit better, i think but the message is just a little bit different:
cannot convert 'void (MyClass::)(int, long)' to 'FunctionType {aka void ()(int, long)}' in initializationI hope you have the solution.
-
Thanks for the really quick reply. It is great!
Unfortunately, it don't want to work. I have got the following message:
cannot convert 'void (MyClass::)(int, long)' to 'FunctionType {aka int ()(int, long)}' in initializationI thought maybe the type of the typedef wrong so i changed that from int to void. It is a bit better, i think but the message is just a little bit different:
cannot convert 'void (MyClass::)(int, long)' to 'FunctionType {aka void ()(int, long)}' in initializationI hope you have the solution.
@CCRfan said in Passing function pointer:
Unfortunately, it don't want to work. I have got the following message
Could you post the code that generates that error - the function definition, the function declaration and the line where you get the pointer and use it?
-
wrote on 21 Sept 2016, 19:49 last edited by
I don't know why changed the forum engine this:
aka int (*)
to this:
aka int()
Should i use a formatting mechanism? -
I don't know why changed the forum engine this:
aka int (*)
to this:
aka int()
Should i use a formatting mechanism?Yes, most certainly. See this thread.
-
wrote on 21 Sept 2016, 20:05 last edited by
The name of the function what i would like pass is: buttonClicked
Important part from the class header file, with function declaration:class A8GS_Widget : public QWidget { Q_OBJECT public: explicit A8GS_Widget(QWidget *parent = 0); ~A8GS_Widget(); LPDIRECT3D9 m_pD3D; LPDIRECT3DDEVICE9 m_pd3dDevice; ENGINE_VARS *ev; void A8GS_start(); EVENT ShowKey(var _ScanCode); void buttonClicked(int, PANEL *); QWidget *A8GS_Widget_parent; bool A8GS_init_stop; signals: public slots: void engineStart(); void engineClose(); void engineBoxSign(); }; typedef void (*ButtonClickType)(int, PANEL *); ButtonClickType pointerToFunction = &A8GS_Widget::buttonClicked;
Important part 1 from the cpp file, the function definition:
void A8GS_Widget::buttonClicked(int buttonId, PANEL *panelId) { qDebug() << "buttonClicked"; qDebug() << buttonId; }
Important part 2 from the cpp file, where i want to pass the function as parameter:
void A8GS_Widget::A8GS_start() { ... pan_setbutton(pan_ize, 0, 0, 104, 226, bmap_1, bmap_1, bmap_1, NULL, (void *)(&A8GS_Widget::buttonClicked), NULL, NULL); ...
I hope i didn't miss nothing.
-
The name of the function what i would like pass is: buttonClicked
Important part from the class header file, with function declaration:class A8GS_Widget : public QWidget { Q_OBJECT public: explicit A8GS_Widget(QWidget *parent = 0); ~A8GS_Widget(); LPDIRECT3D9 m_pD3D; LPDIRECT3DDEVICE9 m_pd3dDevice; ENGINE_VARS *ev; void A8GS_start(); EVENT ShowKey(var _ScanCode); void buttonClicked(int, PANEL *); QWidget *A8GS_Widget_parent; bool A8GS_init_stop; signals: public slots: void engineStart(); void engineClose(); void engineBoxSign(); }; typedef void (*ButtonClickType)(int, PANEL *); ButtonClickType pointerToFunction = &A8GS_Widget::buttonClicked;
Important part 1 from the cpp file, the function definition:
void A8GS_Widget::buttonClicked(int buttonId, PANEL *panelId) { qDebug() << "buttonClicked"; qDebug() << buttonId; }
Important part 2 from the cpp file, where i want to pass the function as parameter:
void A8GS_Widget::A8GS_start() { ... pan_setbutton(pan_ize, 0, 0, 104, 226, bmap_1, bmap_1, bmap_1, NULL, (void *)(&A8GS_Widget::buttonClicked), NULL, NULL); ...
I hope i didn't miss nothing.
It won't work like this. Remember I wrote that static functions can be passed as global functions (C-like functions). Methods (like
buttonClicked
) have to be bound to an object, which is problematic in your case, becausepan_setbutton
expect a C-style function, not a class method. -
It won't work like this. Remember I wrote that static functions can be passed as global functions (C-like functions). Methods (like
buttonClicked
) have to be bound to an object, which is problematic in your case, becausepan_setbutton
expect a C-style function, not a class method.wrote on 21 Sept 2016, 20:18 last edited by@kshegunov said in Passing function pointer:
It won't work like this. Remember I wrote that static functions can be passed as global functions (C-like functions). Methods (like
buttonClicked
) have to be bound to an object, which is problematic in your case, becausepan_setbutton
expect a C-style function, not a class method.OK, and how will work?
If you can see any possible changes, let me share, and i can continue my work. I started to use this Qt tool since one month and i really, really like.
I would appreciate any good proposal.
Thanks in advance. -
@kshegunov said in Passing function pointer:
It won't work like this. Remember I wrote that static functions can be passed as global functions (C-like functions). Methods (like
buttonClicked
) have to be bound to an object, which is problematic in your case, becausepan_setbutton
expect a C-style function, not a class method.OK, and how will work?
If you can see any possible changes, let me share, and i can continue my work. I started to use this Qt tool since one month and i really, really like.
I would appreciate any good proposal.
Thanks in advance.There aren't really good solutions for that one, that's why I was reluctant to propose anything. Your best bet is to use a global pointer to pass the context. Something like this:
class A8GS_Widget : public QWidget { Q_OBJECT // ... static void panSetButton(int, PANEL *); private: static A8GS_Widget * currentWidget; };
And then in the .cpp:
A8GS_Widget * A8GS_Widget::currentWidget = Q_NULLPTR; void A8GS_Widget::panSetButton(int id, PANEL * panelId) { Q_ASSERT(currentWidget); currentWidget->buttonClicked(id, panelId) } void A8GS_Widget::A8GS_start() { // ... currentWidget = this; pan_setbutton(pan_ize, 0, 0, 104, 226, bmap_1, bmap_1, bmap_1, NULL, &A8GS_Widget::panSetButton, NULL, NULL); // ... }
It's not ideal, but it's how this problem is treated most commonly.
-
wrote on 21 Sept 2016, 20:42 last edited by
Thank for your will to help.
I feel myself lucky, because i started another way to solve the problem. It seems to me works.
I have made the following changes:- I added static prefix tag to the function declaration, because i forgot to that earlier
- I moved the following statement from the header to the cpp as the first line of the
void A8GS_Widget::A8GS_start()
ButtonClickType pointerToFunction = &A8GS_Widget::buttonClicked;
- I changed the definition here:
void A8GS_Widget::buttonClicked(int buttonId, PANEL *panelId)
from int buttonId, to var buttonId.
And it works! I like it!
Only one problem remained, i got 1024 as buttonId that should be 1. I think this is my deal with the engine.
Thanks for the quick and kind help.
I am investigate a bit more, and later i set to solved this topic. -
There aren't really good solutions for that one, that's why I was reluctant to propose anything. Your best bet is to use a global pointer to pass the context. Something like this:
class A8GS_Widget : public QWidget { Q_OBJECT // ... static void panSetButton(int, PANEL *); private: static A8GS_Widget * currentWidget; };
And then in the .cpp:
A8GS_Widget * A8GS_Widget::currentWidget = Q_NULLPTR; void A8GS_Widget::panSetButton(int id, PANEL * panelId) { Q_ASSERT(currentWidget); currentWidget->buttonClicked(id, panelId) } void A8GS_Widget::A8GS_start() { // ... currentWidget = this; pan_setbutton(pan_ize, 0, 0, 104, 226, bmap_1, bmap_1, bmap_1, NULL, &A8GS_Widget::panSetButton, NULL, NULL); // ... }
It's not ideal, but it's how this problem is treated most commonly.
wrote on 22 Sept 2016, 19:35 last edited by@kshegunov Thank for the real quick and expert help.
I am happy with that. -
@kshegunov Thank for the real quick and expert help.
I am happy with that.I'm glad I was of help. Happy coding!
1/13