i'm trying to create a new thread with a class "CameraManager" but i have the following error:
cannot convert '*void(CameraManager:: * )(void*) to void*( * )(void*) in pthread_create function
i defined in the cameramanager.h file:
public:
void *dequeueLoop(void *ptr);
and in the cameramanager.cpp
void CameraManager::startDequeuing(){
dequeuing = true;
dequeueThreadId = pthread_create(&dequeueThread, NULL, &CameraManager::dequeueLoop, NULL);
}
void *CameraManager::dequeueLoop(void *ptr){
while(dequeuing){
highSpeedCamera->dequeue();
highSpeedCamera->enqueue();
}
I don't want to declare dequeueLoop as a static function i also tried to declare dequeueLoop as a class friend function in the following way but then it doesn't have scope on class variables 'highSpeedCamera' and 'dequeuing' and the compiler also tell me that 'dequeueLoop' was not declared in this scope
to make dequeueLoop a friend function i did:
cameramanager.h
public:
friend void *dequeueLoop(void *ptr);
cameramanager.cpp
void CameraManager::startDequeuing(){
dequeuing = true;
dequeueThreadId = pthread_create(&dequeueThread, NULL, &CameraManager::dequeueLoop, NULL);
}
void *dequeueLoop(void *ptr){
while(dequeuing){
highSpeedCamera->dequeue();
highSpeedCamera->enqueue();
}
}
Where i'm doing wrong?
I don't want to declare dequeueLoop as a static function
If you want to use pthreads, then you'll need a static or non-member function for the entry point. You can pass a pointer to your object to this function, using it as a trampoline into the non-static member function:
static void * dequeueEntry(void * self) {
return static_cast<CameraManager*>(self)->dequeueLoop();
}
dequeueThreadId = pthread_create(
&dequeueThread, NULL,
&CameraManager::dequeueEntry, // <-- pointer to trampoline function
this); // <-- pointer to object for member function
Alternatively, if you have a modern compiler, you could use the standard thread library instead:
std::thread thread(&CameraManager::dequeLoop, this);
If you want the function to be a member of the class, it must be static. It's because the thread function will be called directly and will not have a valid this pointer. This can be solved by having a wrapper function, that gets passed the actual object and then calls the proper member function:
void *dequeueLoopWrapper(void *p)
{
CameraManager *cameraManager = static_cast<CameraManager*>(p);
camereraManager->dequeueLoop();
return nullptr;
}
// ...
void CameraManager::startDequeuing()
{
dequeuing = true;
dequeueThreadId = pthread_create(&dequeueThread, NULL, dequeueLoopWrapper, this);
}
However, I would recommend you start using the threading support in the new standard library:
void CameraManager::startDequeuing()
{
dequeuing = true;
myThread = std::thread(&CameraManager::dequeueLoop, this);
}
You can't use a pointer to member function as a function pointer unless it's static. You'll have to make dequeueLoop a free function, or write a free function as a wrapper to it.
To access the class members in a free function, you should have the function pass it's this pointer as the final argument of pthread_create. Then have the free function cast it's argument to a pointer to the class.
Related
I receive error:Reference to non-static member function must be called trying to build the following code:
HTTPClient::HTTPClient(int id,HttpListener& message) {
pthread_t thId;
pthread_create(&thId, NULL, processor, this); <--error is here
}
void* HTTPClient::processor(void* userData) {
HTTPClient* client = static_cast<HTTPClient*>(userData);
client->run();
}
void HTTPClient::run() {
while(true) {
pthread_mutex_lock(&mMutex);
pthread_cond_wait(&mCond,&mMutex);
httpLoadFile(mUrl, mPath);
pthread_mutex_unlock(&mMutex);
}
}
I have found some methods trying to solve the error, but failed!
It says you cannot pass pointer to method into pthread_create, you should pass pointer to ordinary function.
This question already has answers here:
pthread function from a class
(9 answers)
Closed 9 years ago.
I have a class named qwerty and a function called compute_ans inside it which takes a void pointer and returns a void pointer. Now when I try to compile, the following statement throws an error
pthread_create (thread_a, NULL, compute_ans, (void*) struct_left);
The definition of the function is void* compute_ans (void* struct_input)
The error is
cannot convert ‘qwerty::compute_ans’ from type ‘void* (qwerty::)(void*)’ to type ‘void* ()(void)’*
You cannot convert a pointer to a non-static member function to a pointer to function, C++ does not allow it. The reason is that member functions take an implicit this pointer as a parameter. Essentially this changes the signature of your function to be something like void* compute_ans(qwerty*, void*). In order to pass the function to pthread_create you need to make the member function static.
class qwerty
{
public:
// ... other member functions and variables ...
// thread start function
static void* compute_ans(void*);
};
If you cannot make this a static member function you will need to pass a pointer to a qwerty object to the thread start function. Looking at the code in your question you also need to pass additional data to the thread function. To do this you can use an additional data structure that contains all the necessary data and pass a pointer to that instead.
class qwerty; // forward declaration
// Structure passed to pthread_create and our helper function
struct thread_data
{
qwerty* qptr; // pointer to qwerty object
void* data; // pointer to other data. change void to your data type.
};
class qwerty
{
public:
// thread start function
static void* start_compute_ans(void* param)
{
// get a pointer to the thread data
thread_data* tdata = static_cast<thread_data*>(param);
// Call the real compute_ans
tdata->qptr->compute_ans(tdata->data);
// Delete the data (use an appropriate smart pointer if possible)
delete tdata;
return NULL;
}
// the real
void compute_ans(void*)
{
// do stuff here
}
};
// Create our thread startup data
thread_data* tdata = new thread_data();
tdata->qptr = qwerty_pointer;
tdata->data = struct_left;
// start the thread data
pthread_create (thread_a, NULL, &qwerty::start_compute_ans, tdata);
You can find the answer here.
You should use static functions to pass to pthread.
class qwerty
{
public:
void compute_ans(void)
{
std::cout << "Compute result!" << std::endl;
return
}
static void hello_helper(void *context)
{
return ((qwerty *)context)->compute_answer();
}
};
...
qwerty c;
pthread_t t;
pthread_create(&t, NULL, &qwerty::hello_helper, &c);
I'm doing to implement thread class for my own using pthread. So, I create Thread class as below :
class Thread
{
public:
Thread()
{
}
virtual void* run(void *params) = 0;
void start(void *params)
{
pthread_create (&threadId, 0, run, params);
pthread_join (threadId, 0);
}
private:
pthread_t threadId;
};
After implementing this class and override virtual run function, I do compile this project. But error: argument of type ‘void* (Thread::)(void*)’ does not match ‘void* (*)(void*)’ occurs. What is wrong in my code?
Thanks in advance :)
Exactly what the compiler is telling you.
pthread_create is expecting a function with the signature :
void* (*)(void*)
Which is a function pointer.
However, you are providing something with this signature:
void* (Thread::)(void*)
Which is not a function pointer, but a pointer to member function. There is a difference : a pointer to member function needs an instance of an object in order to work properly (here, it would need an instance of Thread).
A usual solution would be to make your function run static : it would not be a member function anymore - it doesn't NEED an instance of Thread in order to work properly anymore, and you could pass your current instance as the last parameter of pthread_create in order to act on it once the thread is launched.
You would just need to save the parameters in the class itself.
public:
void start(void *params)
{
this->my_thread_params = params;
pthread_create (&threadId, 0, run, static_cast<void*>(this));
}
private:
static void *run(void *my_object)
{
// here, my_object already contains the params you passed to the function start
static_cast<Thread*>(my_object)->my_member_function();
}
pthread_create is a C function, and knows nothing of C++ member functions. You'll need to give it a static or non-member function, and pass a pointer to your Thread object via the final argument of pthread_create; something like:
class Thread
{
virtual void* run(void *params) = 0;
void start(void * params)
{
this->params = params;
pthread_create(&threadId, 0, &Thread::static_run, this);
}
static void * static_run(void * void_this)
{
Thread * thread_this = static_cast<Thread*>(void_this);
return thread_this->run(thread_this->params);
}
private:
pthread_t threadId;
void *params;
};
Of course in modern C++, this is rather more straightforward:
std::thread thread;
void start(void * params)
{
thread = std::thread([this]{run(params);});
}
(Although of course you shouldn't be using void* to pass your parameters, and there's probably no good reason to wrap the thread up in a class in the first place.)
The error message is telling you that a pointer to a member function in Thread that takes and returns a void* (void* (Thread::*)(void*)) is not convertible to a pointer to function taking and returning the same void*.
While the declaration of the member function may look similar to the type that you need, there is an implicit this pointer of type Thread that needs to be injected on any call to Thread::run
I will like to know, how to make a function where I define a function. And then I can call the defined function. Let me try with a example.
void funcToCall() {
std::cout<<"Hello World"<<std::endl;
}
void setFuncToCall(void func) {
//Define some variable with func
}
void testFuncCall() {
//Call function that has been defined in the setFuncToCall
}
setFuncToCall(funcToCall()); //Set function to call
testFuncCall(); //Call the function that has been defined
I Hope that you understand what I am trying to do here. But I don't know how to bring It down to the right code :-)
You need a function pointer. It's easier to work with function pointers if you typedef them first.
typedef void (*FuncToCallType)();
FuncToCallType globalFunction; // a variable that points to a function
void setFuncToCall(FuncToCallType func) {
globalFunction = func;
}
void testFuncCall() {
globalFunction();
}
setFuncToCall( funcToCall ); //Set function to call,NOTE: no parentheses - just the name
testFuncCall(); //Call the function that has been defined
As other answers have suggested you can use objects like functions, too. But this requires operator overloading (even if it remains hidden from you) and is typically used with templates.
It gives more flexibility (you can set some state to the object before passing it to the function and the object's operator() can use that state) but in your case function pointers may be just as good.
What you want to use is a callback, and is has been answered her : Callback functions in c++
I would advise you to use std::tr1::function ( generalized callback )
C syntax for function pointers is a bit weird, but here we go:
// this is a global variable to hold a function pointer of type: void (*)(void)
static void (*funcp)(void);
// you can typedef it like this:
//typedef void (*func_t)(void);
// - now `func_t` is a type of a pointer to a function void -> void
// here `func` is the name of the argument of type `func_t`
void setFuncToCall(void (*func)(void)) {
// or just: void setFuncToCall(func_t func) {
//Define some variable with func
...
funcp = func;
}
void testFuncCall(void) {
//Call function that has been defined in the setFuncToCall
funcp();
}
setFuncToCall(funcToCall); // without () !
testFuncCall();
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.