Calling pthread_create inside a member function? - c++

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
}

Related

How do I hand over a pointer to a non-static member method to an extern "C" function? [duplicate]

This question already has answers here:
How can I pass a class member function as a callback?
(13 answers)
Closed 2 years ago.
I've got a class named tmc, which now contains (among other things, which are not relevant here) a private constructor, a static factory method, and an instance method named ReadLoop (void*):
extern "C" {
#include <pigpiod_if2.h>
}
class tmc {
public:
static tmc* Initialize ();
static int main ();
private:
void *ReadLoop (void *params);
tmc ();
pthread_t *tmc_receiver_reader;
};
tmc::tmc ()
: tmc_receiver_reader (start_thread (tmc::ReadLoop, NULL))
{
}
void* tmc::ReadLoop (void *params)
{
return params;
}
tmc* tmc::Initialize ()
{
tmc* instance = new tmc ();
return instance;
}
int tmc::main ()
{
return (tmc::Initialize ()) == NULL ? 0 : 1;
}
The issue is now the following: How shall I use the ReadLoop as a function pointer for use with the start_thread () function contained in pigpiod_if2? The code shown here doesn't compile because of the following error:
error: invalid use of non-static member function ‘void* tmc::ReadLoop(void*)’
tmc_receiver_reader (start_thread (tmc::ReadLoop, NULL))
I've seen several questions here at SO with the same error message, but none of them was about a pointer to a non-static member method given to a C function. Please note that even if the object created here is a singleton, I can't make ReadLoop () static. I'm using the g++ 6.5.0 on Raspbian Buster. Thank you.
There is simply no way to use a non-static class method where a standalone function is expected. They are not compatible.
You are going to have to use a static or non-member proxy function instead. Fortunately, start_thread() allows you to pass a user-defined parameter to the function, so you can use that to pass the this pointer of your tmc instance, eg:
class tmc {
...
private:
static void* ReadLoopProxy(void *params);
void* ReadLoop();
tmc ();
pthread_t *tmc_receiver_reader;
};
tmc::tmc ()
: tmc_receiver_reader (start_thread (tmc::ReadLoopProxy, this))
{
}
void* tmc::ReadLoopProxy(void *params)
{
return static_cast<tmc*>(params)->ReadLoop();
}
void* tmc::ReadLoop()
{
return NULL;
}
...
Luckily the C interface provides a void* pass-back to help with this. You can use that to point to the correct tmc object:
extern "C" void* tmc_pigpio_ReadLoop_callback(void* userdata);
class tmc {
// ...
private:
void* ReadLoop();
friend void* tmc_pigpio_ReadLoop_callback(void*);
// ...
};
void* tmc_pigpio_ReadLoop_callback(void* userdata)
{
auto* tmcp = static_cast<tmc*>(userdata);
return tmcp->ReadLoop();
}
// Note "this" passed to start_thread.
tmc::tmc ()
: tmc_receiver_reader (start_thread (tmc_pigpio_ReadLoop_callback, this))
{
}
Or if you were already using the void* userdata for something different, add a tmc* pointer to a struct it points at, or create a new struct containing a tmc* pointer and the other data to pass.

How to multithreading a class member function with pthreads?

I'm trying to run a function named extensionStep from a class named SVAnchor in multi threads. i use this code:
rc = pthread_create(&threads[i], NULL, extensionStep, &td[i]);
to call the function and here is the definition of extensionStep :
void* SVAnchor::extensionStep( void *threadarg)
and i got the following error:
error: cannot convert 'SVAnchor::extensionStep' from type 'void* (SVAnchor::)(void*)' to type 'void* (*)(void*)'
rc = pthread_create(&threads[i], NULL, extensionStep, &td[i]);
^
that shows the problem is converting from type 'void* (SVAnchor::)(void*)' to type 'void* ()(void)'
How to solve this problem?
Thanks all
This should do the job: (After making the function extensionStep static)
rc = pthread_create(&threads[i], NULL, &(SVAnchor::extensionStep), &td[i]);
Or you can create a wrapper function like this:
struct Argument {
SVAnchor* ptr;
int* tid;
}
static void *extensionStepWrapper(void *arg)
{
return (((Argument*)arg)->ptr)->extensionStep(((Argument*)arg)->tid);
}
And use the wrapper:
Argument arg;
arg.ptr = &(class_variable_name); // Use appropriate name (whatever you variable name is for the object of the class SVAnchor)
arg.tid = &(td[i]);
rc = pthread_create(&threads[i], NULL, &(SVAnchor::extensionStepWrapper), &arg);
Note that if you're calling this from inside another member function, you may do this instead:
arg.ptr = this;
You can also create a method in the class to start the thread:
bool StartThread(int* tid){
return (pthread_create(&_thread, NULL, extensionStep, tid) == 0);
}
You might also need to pass the thread as argument of StartThread() function.
This is a common mapping of a class member function to a C-callback:
#include <iostream>
#include <pthread.h>
class Task
{
public:
Task() : thread_id(0) {}
bool start() {
// Passing this as user data to the C-callback.
return pthread_create(&thread_id, 0, invoke, this) == 0;
}
void stop() {
void* no_result;
pthread_join(thread_id, &no_result);
}
private:
Task(const Task&); // no copy (C++11 delete)
Task& operator = (const Task&); // no copy (C++11 delete)
void process() {
std::cout << "Hello\n";
}
// The C-callback has to be static.
static void* invoke(void* self) {
// Note: The invocation takes place in start (passing this)
static_cast<Task*>(self)->process();
// No result passed to join.
return 0;
}
pthread_t thread_id;
};
int main() {
Task task;
task.start();
task.stop();
}
This is a C++11 version:
#include <iostream>
#include <thread>
class Task
{
public:
void operator () () {
std::cout << "Hello\n";
}
};
int main() {
Task task;
std::thread thread(task);
thread.join();
}

cannot convert from type void* (class name)(void*) to type void* (*)(void*) in a pthread

I am trying to create a thread in main function and call a function of another class through my thread.
In main.cpp:
SocketHandler *callserver;
pthread_t thread1;
pthread_create(&thread1,0, callserver->createSocket,NULL);
and in SocketHandler.h:
void* createSocket();
and in SocketHandler.cpp:
void * SocketHandler::createSocket()
{
//....
}
When I am trying to compile main.cpp I am getting an error
cannot convert SocketHandler::createSocket from type void* (SocketHandler::)() to type void* ( * )(void*)
pthread_create() accepts only pointers to regular functions or class functions, not to member functions. And that pointer must be void *(*)(void *). To workaround you can do next:
void *trampoline(void *arg) {
SocketHandler *callServer = static_cast<SocketHandler *>(arg);
callServer->createSocket();
return nullptr;
}
// ...
SocketHandler *callserver;
pthread_t thread1;
pthread_create(&thread1,0, trampoline, callserver);
trampoline() may be inlined:
pthread_create(&thread1, 0, [](void* ptr){static_cast<SocketHandler*>(ptr)->createSocket(); return (void*)nullptr;}, callserver);
Alternatively you may use std::thread, that allows painless using of member functions too.

Boost thread not calling thread function

I am trying to create a boost thread and I see the thread is created but the control does not come to the thread function. Can someone please explain why is it so?
Please see below for the code used.
header_file.h
class fa {
public:
fa();
~fa();
int init(void);
static void* clThreadMemFunc(void *arg) { return ((fa*)arg)->collectData((fa*)arg); }
void* collectData(fa *f );
private:
int m_data;
boost::thread *m_CollectDataThread;
};
`
test.cpp
int fa::init(void)
{
if (m_CollectDataThread== NULL)
{
printf("New Thread...\n");
try
{
m_CollectDataThread =
new boost::thread((boost::bind(&fanotify::clThreadMemFunc, this)));
}
catch (...){perror("Thread error ");}
printf("m_CollectDataThread: %p \n", m_CollectDataThread);
}
return 0;
}
void* fa::collectData(fa *f)
{
printf("In collectData\n");
int data = f->m_data;
printf("data %d",data);
}
The test.cpp is complied/built as a library (test.so) and another main function calls the init function. I see the variable m_collectDataThread value changing from null to some value (thread gets created) and also catch does not get any exception.
But I don't see any statement in collectData getting printed. Why is the thread not able to reach it?
Perhaps try adding a join.
E.g.
try
{
m_CollectDataThread =
new boost::thread(boost::bind(&fanotify::clThreadMemFunc, this));
m_CollectDataThread->join();
}
When you use boost::thread or std::thread you do not need old way of passing thread function (using static method and casting void * pointer), you can call class method directly:
class fa {
public:
fa();
~fa();
int init(void);
void collectData();
private:
int m_data;
boost::thread *m_CollectDataThread;
};
m_CollectDataThread = new boost::thread( &fa::collectData, this );
// or explicitly using bind
m_CollectDataThread = new boost::thread( boost::bind( &fa::collectData, this ) );
boost is C++ library, not C

How to Convert Address to Function Pointer to Call Method

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++