I have a function called by a thread.this function has a unique argument which is queue::my_queue . So I need to perform a cast on void pointer in the method called by the thread as follows:
void *AddPacket(void *Ptr)
{ queue<int> my_queue = (queue*)Ptr ;
my_queue.push(byte) ;
}
and in the main, I do:
int main()
{ // do business
pthread_create(&thread, NULL, &AddPacket, (void*)queue) ;
}
But both conversions are wrong.
the first conversion leads to the error:
request for member ‘push' in ‘my_queue’, which is of non-class type ‘queue*’
and the second one:
invalid cast from type ‘queue’ to type ‘void*’
How can I solve the problem?
You try to cast object type to pointer type. It is not allowed. I guess you are new to C++, so I post corrected code here to unpuzzle you and get you going, but please read a book on C++:
queue<int>* my_queue = (queue<int>*)Ptr ;
my_queue->push(byte) ;
pthread_create(&thread, NULL, &AddPacket, &queue) ;
Remember to read about pointers on C++ :)
Try:
queue<int> *my_queue = (queue<int> *)Ptr ;
my_queue->push(byte) ;
pthread_create(&thread, NULL, &AddPacket, (void*)&queue) ;
.. something along those lines, anyway
You need to change both the thread function and the thread creation:
// thread entry point:
void *AddPacket(void *Ptr)
{
reinterpret_cast<std::queue<int>*>(Ptr)->push(byte);
}
// thread creation:
std::queue<int> q;
pthread_create(&thread, NULL, &AddPacket, &q);
// ^^^^ **pointer** to "q";
// conversion to void* is implied
Related
Okay so i'm looking at the documentation for pthread_create and I just don't understand at all how to do what I want to do.
I want to call pthread_create which will obv pass in a struct of pthread_t. But the function I pass to it takes in a pointer to a of MyNode*. How would I pass the function as a parameter and pass it "this" as a parameter to that function.
//MyNode field and method in class file
pthread_t myTrd;
static void compute(MyNode* node);
////////////////////////////////////////////////////////////
//Actual code in header file below
static void MyNode::compute(*MyNode node){ //L61
//code
}
void MyNode::run(){ //run function in header file
pthread_create(&(this->thread),NULL,MyNode::compute, this);
}
outcome:
myNode.cpp:61: error: 'static' may not be used when defining (as opposed to declaring) a static data member
myNode.cpp:61: error: 'int MyProjectGraph::MyNode::compute' is not a static member of 'class MyProjectGraph::MyNode'
myNode.cpp:61: error: expected primary-expression before 'node'
myNode.cpp:61: error: expected ',' or ';' before '{' token
myNode.cpp:134: error: expected `}' at end of input
The function passed to pthread_create() should match the prototype:
void *function(void *arg);
If your function does not match that, you have to use brute force and ignorance (and a cast) to make the function pointer acceptable — and then hope that the alternative interface doesn't break anything.
It is far better to make your function match the specification:
void *function(void *arg)
{
MyNode *mnp = (MyNode *)arg;
…
return 0;
}
The return can return some more meaningful value if you have one available, but returning a null (you could probably write nullptr given that you're mainly using C++).
Note that pthread_create() is usually a C function itself and expects C function semantics in the function pointer it is passed.
Having a thread per object isn't really a good way to go. I presume that
since you are calling your object a node, you have a bunch of them
and want to do something to them on a thread.
I typically do the following, which is a classic idiom:
class Worker
{
struct ThreadStr
{
Worker * worker;
// put parameters here
MyNode * node;
};
public:
static void *StaticHandler(void *pvoid)
{
ThreadStr * data = (ThreadStr*)pvoid;
data->worker->Compute(data->node);
delete data;
return NULL;
}
void Compute(MyNode *node)
{
// whatever you want to compute on a node.
}
// start a thread to execute Worker::Compute(MyNode*)
void Run(MyNode *node)
{
ThreadStr * data = new ThreadStr();
data->worker = this;
data->node = node;
pthread_t threadId;
pthread_create(&threadId, NULL, Worker::StaticHandler, data);
}
};
I have the following encapsulation for my pthread_t threads:
#include <pthread.h>
class Thread
{
public:
void run(const int);
static void *run_helper(void *);
bool startThread(int);
void joinThread();
pthread_t th;
};
Where run is my thread routine, and run_helper is the following:
void *Thread::run_helper(int num)
{
return (Thread *)this->run(num);
}
I start my threads like such:
bool Thread::startThread(intptr_t arg)
{
return (pthread_create(&this->th, NULL, &run_helper(arg), (void *)(intptr_t)arg));
}
But when I compile, I get the following errors:
error: lvalue required as unary ‘&’ operand
return (pthread_create(&this->th, NULL, &run_helper(arg), (void *)(intptr_t)arg));
error: ‘this’ is unavailable for static member functions
return (Thread *)this->run(num);
And despite trying, I can't seem to make this encapsulation work.
I think your issue might specifically be &this->th. & has higher precedence than ->. Perhaps try &(this->th).
For the first error, you need to cast the third argument into (void*(*)(void*)) and remove & (maybe the casting isn't neccessary).
pthread_create(&this->th, NULL, (void*(*)(void*))run_helper(arg), (void *)(intptr_t)arg);
The second error, you are trying to use pointer to this in a static function, but the function isn't called on any object, therefore you can't use this in a function like that. The solution is to cast arg into Thread* and then call the non-static run 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 am trying to use pthread_create() but it always gives me this error invalid conversion from void* to void* ( * )(void*)
This error is in the 3rd argument. Could someone help me with this error ?
void Print_data(void *ptr) {
cout<<"Time of Week = " <<std::dec<<iTOW<<" seconds"<<endl;
cout<<"Longitude = "<<lon<<" degree"<<endl;
cout<<"Latitude = "<<lat<<" degree"<<endl;
cout<<"Height Above Sea = "<<alt_MSL<<" meters"<<endl;
}
int call_thread()
{
pthread_create(&thread, NULL, (void *) &Print_data, NULL);
return 0;
}
The error is that you're converting the function pointer (void* (*)(void*)) to an object pointer (void*), when pthread_create expects a function pointer for that argument. There's no implicit conversion to undo the dodgy conversion you've done, hence the error.
The answer is to not do that:
pthread_create(&thread, NULL, &Print_data, NULL);
and you'll also need to modify Print_data to return void* to match the Posix threads interface:
void *Print_data(void *ptr) {
// print stuff
return NULL; // or some other return value if appropriate
}
As noted in the comments, there are various other issues with using this C library directly from C++; in particular, for portability, the thread entry function should be extern "C". Personally, I'd recommend using the standard C++ thread library (or Boost's implementation, if you're stuck with a pre-2011 version of the language).
You're trying to convert a function pointer into a void* here: (void *) &Print_data
According to pthread_create you need to pass in a function that takes a void* and returns a void*
So your function signature should be
void* Print_data(void *ptr)
And your call should be
pthread_create(&thread, NULL, &Print_data, NULL);
pthread_create takes the third argument as
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void*),
void *arg);
This, void *(*start_routine)(void*) is a pointer to a function that takes a void* pointer and returns a void* pointer.
When you do &Print_data and convert the pointer to void * , it means you are passing a pointer of type void* and not a pointer of type void *(*start_routine)(void*) [function pointer].
To be correct, you need to make your return type as void* and make the call as pthread_create(&thread, NULL, &Print_data, NULL);
You must return void*
void* Print_data(void *ptr) {
to satisfy the needs.
The signature of the function to be passed is
void* function(void*);
then call pthread_create using
pthread_create(&thread, NULL, &Print_data, NULL);
add header file #include
and compile g++ -lpthread
Not sure what is wrong with parameter 3 or the setup?
error C2440: 'type cast' : cannot convert from '' to 'unsigned long (__stdcall *)(void *)'
None of the functions with this name in scope match the target type
--
void CNumbergeneratorDlg::OnBtn3()
{
//CreateThread
hThread1 = CreateThread(NULL, 0, Thread1, this, 0, NULL);//<--is "this" correct
WaitForSingleObject(hThread1,INFINITE);
TerminateThread(hThread1,0);
CloseHandle(hThread1);
}
DWORD WINAPI CNumbergeneratorDlg::Thread1(LPVOID iValue)
{
CreateNumber();
return 0;
}
??? casting for "this"
DWORD WINAPI CNumbergeneratorDlg::Thread1(LPVOID iValue)
{
(CDialog)iValue->CreateNumber();
return 0;
}
xxxxxxxxxxxxxxx
xxxxxxxxxxxxxxx
This is what I did with your guys input... thanks
void CNumbergeneratorDlg::OnBtn3()
{
//CreateThread
CNumbergeneratorDlg *pp = this;
hThread1 = CreateThread(NULL, 0, Thread1, pp, 0, NULL);
// WaitForSingleObject(hThread1,INFINITE);
// TerminateThread(hThread1,0);
// CloseHandle(hThread1);
}
DWORD WINAPI CNumbergeneratorDlg::Thread1(LPVOID iValue)
{
CNumbergeneratorDlg *pp = (CNumbergeneratorDlg*)iValue;
pp->CreateNumber();
return 0;
}
void CNumbergeneratorDlg::CreateNumber()
{
long m;
j = 0;
for(long i = 0; i < 1000;i++){
m = 0;
for(long k = 0; k < 1000000;k++){
m ++;
}
j++;
}
AfxMessageBox("Done count");
TerminateThread(hThread1,0);
CloseHandle(hThread1);
}
void CNumbergeneratorDlg::OnBtn4()
{
TerminateThread(hThread1,0);
CloseHandle(hThread1);
CString c;
c.Format("%d", j);
MessageBox(c);
}
You're trying to pass CreateThread a class method which doesn't have the signature it expects. The first argument of all methods is the same type of the this pointer, in the case of Thread1, an CNumbergeneratorDlg*.
You should:
Make the method Thread1 static, or
Move it outside the class.
Here is an article on static methods which shows how you should use static in this situation:
http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fcplr039.htm
Here is an article that may be of use when using CreateThread:
http://adilevin.wordpress.com/2009/06/07/createthread-an-example/
I also suggest you read the following, to understand calling conventions (the '__stdcall' bit):
http://msdn.microsoft.com/en-us/library/zxk0tw93(v=vs.80).aspx
Thread1 is a non-static member function. Calling it requires an instance of your class (CNumbergeneratorDlg). That's why you get that error.
You could make Thread1 static, and pass this by parameter when creating the thread:
class CNumbergeneratorDlg {
void OnBtn3() {
hThread1 = CreateThread(NULL, 0, Thread1, this, 0, NULL);
// ...
}
public:
static DWORD Thread1(LPVOID lpdwThreadParam) {
CNumbergeneratorDlg *instance =
static_cast<CNumbergeneratorDlg *>(lpdwThreadParam);
// do something with instance.
}
};
Did you declare the function Thread1 as a static member function in CNumbergeneratorDlg? If not, please do so.
Non-static class functions have an implicit additional parameter for this. So, type casting will not work. On the other hand, static methods do not carry this parameter.
Then, you might wonder how you can access class members inside Thread1. A typical technique is passing this via iValue.