How to Convert Address to Function Pointer to Call Method - c++

I wanted to call Test1() Method Within WaitAndCallFunc() Function.
Code:
typedef void (*func)();
void StartTimer(void* pFuncAddr);
void WaitAndCallFunc(void* pPtr);
void WaitAndCallFunc(void* pPtr)
{
int i = 0;
int nWaitTime = 3;
while(1)
{
Sleep(1000);
// I want pPtr to call Test1 Function;
if(i == nWaitTime)
break;
}
_endthread();
}
void StartTimer(void* pFuncAddr)
{
_beginthread(WaitAndCallFunc, 0, pFuncAddr);
}
void Test1();
int main(int argc, char* argv[])
{
StartTimer(Test1);
Sleep(5000);
return 0;
}
void Test1()
{
cout << "Testing Thread\n";
}

I'm not sure I understand what your question is exactly, but try this:
((func)pPtr)();

Cast and call:
typedef void (*func)();
void WaitAndCallFunc(void* pPtr)
{
int i = 0;
int nWaitTime = 3;
while(1)
{
Sleep(1000);
func f=(func)pPtr; // cast to correct pointer to function type
f(); // and call!
if(i == nWaitTime)
break;
}
_endthread();
}

Strictly in C you're not supposed to convert between function pointers and other types of pointers. It's not guaranteed to work how you expect.
So a more pedantically correct version would look something like:
struct hook {
void (*func)();
};
void StartTimer(void* pFuncAddr);
void WaitAndCallFunc(void* pPtr);
void WaitAndCallFunc(void* pPtr)
{
struct hook *hook_ptr = pPtr;
hook_ptr->func();
_endthread();
}
void StartTimer(void* pFuncAddr)
{
_beginthread(WaitAndCallFunc, 0, pFuncAddr);
}
void Test1();
int main(int argc, char* argv[])
{
struct hook hook_test1 = { &Test1 };
StartTimer(&hook_test1);
Sleep(5000);
return 0;
}
Note that in this it's the struct pointer that's cast to and from void *, not the function pointer itself. This also has the advantage that you can stuff some more values into the struct, if you need them to be passed down to Test1().

Actually, converting a function pointer to a void* or a void* to a function pointer is not directly allowed in current C or C++ - even though most compilers compile it.
There are two ways to convert back and forth (using C syntax) on compilers that don't compile the direct cast:
Method 1 (convert first to an integral intermediary)
((func) (intptr_t) pPtr)(); // call the void*
StartTimer( (void*) (intptr_t) &Test1); // pass function pointer to void*
Method 2 (use void**)
func f = 0;
*((void**)&f) = pPtr;
f();
StartTimer( *((void**) &Test1)); // pass function pointer to void*
You can refer to the following thread for more of an explanation: Function pointers casting in C++

Related

How to acess member variable from a static function

i need to register to a callback function provided by a third party dll, this function does not accept any arguments, and hence i cannot pass in the "this" to it. here the pData is the just the data.
//This is declared as static function in my class
void CMyClass::ThirdPartyCallBack(void *pData)
{
//How to access the member variables of the class
}
how to do this without using a global variable, appreciate you attention and time
A void* is a pointer to whatever you like. You can pass anything you like as the data pointer to the dll, for example "this". And in your callback, you convert it back to an object pointer.
You can create a table of context pointers that is associated with a table of 'thunks' that are used as the callback function(s) you give to the DLL:
class foo {
public:
void callback(void* data);
};
enum {
kMAX_CALLBACKS = 3,
};
foo* context_table [kMAX_CALLBACKS] = {
0,
0,
0
// however many you might need...
};
extern "C" void callback_0( void* data)
{
foo* ctx = context_table[0];
ctx->callback(data);
}
extern "C" void callback_1( void* data)
{
foo* ctx = context_table[1];
ctx->callback(data);
}
extern "C" void callback_2( void* data)
{
foo* ctx = context_table[2];
ctx->callback(data);
}
// ....
extern "C" {
typedef void (*dll_callback)(void*);
}
dll_callback callback_table[kMAX_CALLBACKS] = {
callback_0,
callback_1,
callback_2
// however many you might need...
};
dll_callback set_callback_context(foo* ctx)
{
for (int i =0; i < kMAX_CALLBACKS; ++i) {
if (context_table[i] == 0) {
context_table[i] = ctx;
return callback_table[i];
}
}
return 0;
}
void clear_callback_context(foo* ctx)
{
for (int i =0; i < kMAX_CALLBACKS; ++i) {
if (context_table[i] == ctx) {
context_table[i] = 0;
return;
}
}
}
Now when you need to set up a callback to foo::callback() pass the DLLs function that sets up the callback with something like:
third_party_set_callback( set_callback_context(foo_instance_ptr));
and the callback will end up at foo:callback() with the appropriate this pointer.

initialize struct array as c++ class member

I have class
Class A{
};
typedef struct
{
const char *dec_text;
void (A::*TestFun)();
} Test ;
Test _funs[] = {{"testLogOK", &A::testLogOK},
{"testLoginException", &A::testLoginException}
};;
How can i initialize this Test Array in construct method. The _funs tracks the A's method name and corresponding address, the methods which like:
void (methodName) (void)
In construction method, both below ways fail:
_funs = {{"testLogOK", &A::testLogOK},
{"testLoginException", &A::testLoginException}
};
The other question is how can i invoke the function pointer.. I tried the way like:
int
A::run (const char *name, int argc, ACE_TCHAR *argv[])
{
for(int i=0; i< sizeof(_funs)/sizeof(Test); i++){
Test test = _funs[i];
*(test.testFun)(); //this->*(test.fun)(); Both fail with same error
//(this->*(test.fun))() works
}
}
The compile also fails with message:
error C2064: term does not evaluate to a function taking 0 arguments
[UPdate]
I removed the struct Test and Test _funs out of Class A. But still have problem in A's method:
int A::run (const char *name, int argc, ACE_TCHAR *argv[])
The testLogOK and testLoginException method do exist as member functions of class A
Try this:
class A
{
public:
struct Test
{
const char *dec_text;
void (A::*TestFun)();
};
A(Test tt[])
{
for (int i=0; tt[i].dec_text; i++)
_funs[i] = tt[i];
}
void f1() { printf("this is f1\n"); }
void f2() { printf("this is f2\n"); }
void f3() { printf("this is f3\n"); }
Test _funs[100];
};
A::Test tt[] =
{
{ "Function f1", &A::f1},
{ "Function f2", &A::f2},
{ "Function f3", &A::f3},
{0, 0}
};
void test()
{
A a(tt);
(a.*(a._funs[0].TestFun))();
A *pa = new A(tt);
(pa->*(pa->_funs[1].TestFun))();
delete pa;
// EDIT: call f3
(a.*(tt[2].TestFun))(); // this will call directly from the global table
}
This will invoke the function assigned to the pointer.
This can be improved quite a bit if you typedef the pointer to the member
typedef void (A::*PF_T)();
and use a std::map as container:
std::map<std::string, PF_T> func_map;
It can be streamlined a lot more, but I hope it helps up to this point.

Passing a member function as parameter of a member function

I'm busy with making a leveleditor class in an engine but I'm stuck at passing a member function as parameter of another member function.
First I've made a typedef
typedef void (LevelEditor::*CallFunctionPtr)();
Then I have made a member function to check if the user clicks with his mouse on a hitregion. If so, another function needs to be called. So I've my first member function with 2 parameters
LevelEditor.h
void CheckClickCollision(HitRegion* region, CallFunctionPtr callFunctionPtr);
LevelEditor.cpp
void LevelEditor::CheckClickCollision( HitRegion* region, CallFunctionPtr callFunctionPtr)
{
if(GAME_ENGINE->GetLButtonMouseState())
{
if(!m_bIsLeftPressed && region->HitTest(m_MousePosition))
(this->*callFunction)();
m_bIsLeftPressed = true;
}
else
m_bIsLeftPressed = false;
}
Then I've two stupid example member functions:
LevelEditor.h
void LevelUp();
void LevelDown();
LevelEditor.cpp
void LevelEditor::LevelUp()
{
++m_iCurrentLevel;
}
void LevelEditor::LevelDown()
{
if(m_iCurrentLevel > 0)
--m_iCurrentLevel;
else
return;
}
And now I want to call that function every tick to check if there is a hit. So in my tick function:
CheckClickCollision(m_LeftArrowRegionPtr, LevelDown);
CheckClickCollision(m_RightArrowRegionPtr, LevelUp);
And here I get the error on LevelDown and Levelup:
Error: argument of type void (LevelEditor::*)()" is incompatible with parameter of type "CallFunctionPtr *"
Dont know how to fix it. Tried different things, nothing worked
Try
CheckClickCollision(m_LeftArrowRegionPtr, &LevelEditor::LevelDown);
CheckClickCollision(m_RightArrowRegionPtr, &LevelEditor::LevelUp);
For your convenience, here's the working sample (the compiler is GCC 4.7):
#include <stdio.h>
class LevelEditor;
typedef void (LevelEditor::*CallFunctionPtr)();
class LevelEditor
{
public:
LevelEditor() {}
void CheckClickCollision(void* region, CallFunctionPtr callFunction)
{
(this->*callFunction)();
}
void LevelUp() { printf("up\n"); }
void LevelDown() { printf("down\n"); }
void Test()
{
CheckClickCollision(NULL, &LevelEditor::LevelDown);
CheckClickCollision(NULL, &LevelEditor::LevelUp);
}
};
int main()
{
LevelEditor e;
e.Test();
return 0;
}
The other way to call this:
void Test()
{
CallFunctionPtr p;
p = &LevelEditor::LevelDown;
CheckClickCollision(NULL, p);
p = &LevelEditor::LevelUp;
CheckClickCollision(NULL, p);
}
You need to use std::function and std::bind, or lambdas if you have a supporting compiler.
void LevelEditor::CheckClickCollision( HitRegion* region, std::function<void()> callFunction)
{
if(GAME_ENGINE->GetLButtonMouseState())
{
if(!m_bIsLeftPressed && region->HitTest(m_MousePosition))
callFunction();
m_bIsLeftPressed = true;
}
else
m_bIsLeftPressed = false;
}
void Test()
{
// lambda
CheckClickCollision(NULL, [this] { LevelDown(); });
// bind
CheckClickCollision(NULL, std::bind(&LevelEditor::LevelDown, this));
}

Calling pthread_create inside a member function?

I created a widget.h file containing the declartions of pthread_function and I wanted to call it in a member function destroyWidget of that class Widget in widget.cpp. but always shows an error. I'll show the .cpp and .h file.
widget.h file
class Widget
{
public:
Widget();
void createWidget(int x,int y,int w,int h);
void showWidget();
int wid;
pthread_t thread;
int *incomingval,id;
void join();
Window win;
XEvent evt;
private:
void* destroyWidget(void* ptr);
Display *disp;
int screenNumber;
unsigned long white;
unsigned long black;
long eventMask;
GC gc;
int tbit;
int *incoming,val;
};
now the widget.cpp
Widget::Widget()
{
disp=XOpenDisplay( NULL );
screenNumber=DefaultScreen(disp);
white=WhitePixel(disp,screenNumber);
black=BlackPixel(disp,screenNumber);
eventMask=StructureNotifyMask;
tbit=0;
}
void Widget::createWidget(int x,int y,int w,int h)
{
wid=w;
win= XCreateSimpleWindow(disp,DefaultRootWindow(disp),x,y,w,h,1,white,black);
}
void Widget::showWidget()
{
XMapWindow(disp,win);
XFlush(disp);
gc=XCreateGC(disp,win,0,NULL);
XSetForeground(disp,gc,white);
XDrawLine(disp,win,gc,wid-10,0,wid,10);
XDrawLine(disp,win,gc,wid-10,10,wid,0);
//calling the thread function
pthread_create( &thread, NULL, destroyWidget, this);
}
void Widget::join()
{
pthread_join( thread, NULL);
}
void* Widget::destroyWidget(void* ptr)
{
Widget* mw = static_cast(ptr);
eventMask=ButtonPressMask|ButtonReleaseMask;
XSelectInput(disp,win,eventMask);
do{
printf("id= %d",id);
XNextEvent(disp,&evt);
}while(evt.type!=ButtonRelease);
XDestroyWindow(disp,win);
XCloseDisplay(disp);
return NULL;
}
now the main.cpp file
#include "widget.h"
#include
int main()
{
Widget* w=new Widget();
Widget* n=new Widget();
n->createWidget(20,20,150,150);
w->createWidget(50,50,250,250);
n->showWidget();
w->showWidget();
n->join();
w->join();
return 0;
}
the error is
widget.cpp: In member function ‘void Widget::showWidget()’:
widget.cpp:44:51: error: argument of type ‘void* (Widget::)(void*)’ does not match ‘void* (*)(void*)’
The problem is that pthread_create is a C-style function; you need to give it a pointer-to-function. Widget::destroyWidget() is a pointer-to-member-function. (Remember that non-static member functions always have an implied this argument, which pthread_create doesn't know how to provide.)
See the answers to this question for some possible solutions: pthread function from a class.
The third argument to pthread_create has the signature (in C++):
extern "C" void* (*pointerToFunction)( void* );
You're trying to pass it the address of a member function:
void* (Widget::*pointerToMemberFunction)( void* );
The signatures are incompatible: the second requires an object on which
to call it, and is not extern "C".
The simplest way of handling this is to use boost::thread, with all
it's functional object support. Otherwise, you can define something
like the following:
struct AbstractTask
{
virtual ~AbstractTask() {}
virtual void* run() = 0;
};
template<typename T, void* (T::*ptr)()>
class Task
{
T* myObject;
public:
Task( T* object ) : myObject( object ) {}
virtual void* run()
{
return (myObject->*ptr)();
}
};
extern "C" void* taskRunner( void* arg )
{
std::auto_ptr<AbstractTask> p( static_cast<AbstractTask*>( arg ) );
return p->run();
}
pthread_t taskStarter( AbstractTask* obj )
{
pthread_t result;
pthread_create( &result, NULL, &taskRunner, obj );
return result;
}
To start a thread, you then call:
thread = taskStarter( new Task<Widget, &Widget::destroyWidget>( this ) );
(This is from memory, from an earlier project, so there might be some
typos in it, but you get the idea. And you probably want to add some
error handling in taskStarter.)
Like Oli said you can't use a member function when a C-style function expects a "normal" function pointer. However, what you can do is make a separate function that calls back your destroyWidget() method.
Like so:
void* start_routine(void* arg)
{
Widget* widget = static_cast<Widget* >(arg);
widget->destroyWidget();
return NULL;
}
void Widget::showWidget()
{
pthread_create(&thread, NULL, &start_routine, this);
}
void Widget::destroyWidget()
{
// your code
}

C++ Class member callback

I have an error compiling this code:
template <class T> class purple_multitimer {
public:
typedef struct _timerinfo timerinfo, *ptimerinfo;
typedef gboolean (T::*multitimer_callback) (ptimerinfo pti);
typedef struct _timerinfo {
guint id;
multitimer_callback cb;
T * pthis;
purple_multitimer<T> * pmt;
} timerinfo, *ptimerinfo;
purple_multitimer() {
memset(m_ti, 0, sizeof(m_ti));
}
~purple_multitimer() {
stop();
}
void start(multitimer_callback mt_cb, T * pthis, guint timeout = 10) {
ptimerinfo pti = ti_get();
assert(pti);
pti->pthis = pthis;
pti->pmt = this;
pti->cb = mt_cb;
pti->id = purple_timeout_add_seconds(timeout, GSourceFunc(timeout_cb), pti);
}
void stop(multitimer_callback mt_cb = NULL) {
for (register guint n = 0; n < sizeof(m_ti)/sizeof(timerinfo); ++ n)
if (m_ti[n].cb == mt_cb) {
purple_timeout_remove(m_ti[n].id);
ti_zero(n);
}
}
private:
timerinfo m_ti[32];
inline ptimerinfo ti_get(guint n) {
return &m_ti[n];
}
inline ptimerinfo ti_get() {
for (register guint n = 0; n < sizeof(m_ti)/sizeof(timerinfo); ++ n)
if (m_ti[n].id == 0) return &m_ti[n];
return NULL;
}
inline ptimerinfo ti_zero(ptimerinfo pti) {
memset(pti, 0, sizeof(timerinfo));
return pti;
}
inline ptimerinfo ti_zero(guint n) {
memset(&m_ti[n], 0, sizeof(timerinfo));
return &m_ti[n];
}
static gboolean timeout_cb(ptimerinfo pti) {
gboolean res = (pti->pthis->*(pti->cb))(pti);
if (!res) pti->pmt->stop(pti->cb);
return res;
}
};
class _ctrl {
public:
purple_multitimer<_ctrl> pmt;
gboolean on_tomeout (purple_multitimer<_ctrl>::ptimerinfo pti) {
return false;
};
void on_connected(PurpleConnection *gc) {
pmt.start(purple_multitimer<_ctrl>::multitimer_callback(&_ctrl::on_tomeout), this);
}
void on_disconnected(PurpleConnection *gc) {
}
} controller;
When compiling this code got error:
[Error] E:\dnc-imexchange\dnc-imexchange.cpp:117: error: no matching function for call to `purple_multitimer<_ctrl>::start(gboolean (_ctrl::*)(_timerinfo*), _ctrl* const)'
[Warning] E:\dnc-imexchange\dnc-imexchange.cpp:52: note: candidates are: void purple_multitimer<T>::start(gboolean (T::*)(_timerinfo*), T*, guint) [with T = _ctrl]
I need to implement callbacks in such way.
If you want some good quality callbacks (able to call multiple functions at once, suitable for observer pattern), may I suggest boost::signals2.
If you just want to call one function as a callback you can use std::function:
void Foo(const std::function<bool (const int)> &callback)
{
const int number = 4;
if (callback(number))
{
std::cout << "Callback returned true!" << std::endl;
}
else
{
std::cout << "Callback returned false!" << std::endl;
}
}
// Use this if you have C++11
void CallFooLambda()
{
const auto lambda = [](const int number) -> bool
{
return number % 2;
};
Foo(lambda);
}
// Else use these functions
bool FooCallback(const int number)
{
return number % 2;
}
void CallFoo()
{
Foo(&FooCallback);
}
The _ctrl is a const pointer, and the function you try to call require a non-const ptr-to _ctrl (pthis).
Can you define pthis as follows?
T *pthis const
That should make your code match the 'candidate' in the error message.
this is a pointer that you can't change.
Boost.Function is a good toolkit for simplifying callback syntax and implementation.
The Boost.Function library contains a
family of class templates that are
function object wrappers. The notion
is similar to a generalized callback.
It shares features with function
pointers in that both define a call
interface (e.g., a function taking two
integer arguments and returning a
floating-point value) through which
some implementation can be called, and
the implementation that is invoked may
change throughout the course of the
program.
Generally, any place in which a
function pointer would be used to
defer a call or make a callback,
Boost.Function can be used instead to
allow the user greater flexibility in
the implementation of the target.
Targets can be any 'compatible'
function object (or function pointer),
meaning that the arguments to the
interface designated by Boost.Function
can be converted to the arguments of
the target function object.