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.
Related
I'm trying to create a class to abstract some basic behavior of libuv's networking functions.
#define TCP_BACKLOG 256
class _tcp {
uv_tcp_t* tcp = NULL;
public:
~_tcp() { delete tcp; }
void listen_uv_listen_uv_connection_cb(uv_stream_t* stream, int status) {
printf("NEW CONNECTION\n");
}
void listen(const char* host, int port) {
tcp = new uv_tcp_t();
uv_tcp_init(uv_default_loop(), tcp);
sockaddr_in* addr = new sockaddr_in();
uv_ip4_addr(host, port, addr);
uv_tcp_bind(tcp, (const sockaddr*)addr, 0);
delete addr;
uv_listen((uv_stream_t*)tcp, TCP_BACKLOG, listen_uv_listen_uv_connection_cb);
}
};
The problem with the previously shown code is that when I try to compile it I get the following error:
error: reference to non-static member function must be called
on: uv_listen((uv_stream_t*)tcp, TCP_BACKLOG, listen_uv_listen_uv_connection_cb);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
And it points to listen_uv_listen_uv_connection_cb as the culprit.
Can someone explain to me, why is that an error, and how am I supposed to fix it?
The uv_listen() and uv_connection_cb signatures are declared as follows
UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);
typedef void (*uv_connection_cb)(uv_stream_t* server, int status);
You cannot convert non-static member function to a pointer to function even with the same signature, as technically member function has a hidden parameter called this. One of the solution is to make listen_uv_listen_uv_connection_cb static:
class _tcp {
uv_tcp_t* tcp = NULL;
public:
~_tcp() { delete tcp; }
static void listen_uv_listen_uv_connection_cb(uv_stream_t* stream, int status) {
printf("NEW CONNECTION\n");
}
void listen(const char* host, int port) {
tcp = new uv_tcp_t();
uv_tcp_init(uv_default_loop(), tcp);
sockaddr_in* addr = new sockaddr_in();
uv_ip4_addr(host, port, addr);
uv_tcp_bind(tcp, (const sockaddr*)addr, 0);
delete addr;
uv_listen((uv_stream_t*)tcp, TCP_BACKLOG,
&_tcp::listen_uv_listen_uv_connection_cb);
}
};
PS to be able to call a non-static method you would need a way to get a pointer to your _tcp instance from "uv_stream_t* stream" parameter. I would suggest to use "void* uv_handle_t.data" pointer from this doc http://docs.libuv.org/en/latest/handle.html#c.uv_handle_t
static void listen_uv_listen_uv_connection_cb(uv_stream_t* stream, int status) {
_tcp *tcp = static_cast<_tcp *>( stream->data );
tcp->regularMethod();
}
Of course you should assign this pointer to uv_handle_t.data when you initialize uv_tcp_t *:
void listen(const char* host, int port) {
tcp = new uv_tcp_t();
uv_tcp_init(uv_default_loop(), tcp);
tcp->data = this; // do not forget it
...
}
and I would move this initialization code to constructor.
You would need such static wrapper for every callback you are going to use with this library. With c++11 you probably can use lambda instead.
The uv_listen() call back connector expects a static or free (outside class) function.
Thus you should declare your function like this
static void listen_uv_listen_uv_connection_cb(uv_stream_t* stream, int status) {
printf("NEW CONNECTION\n");
_tcp* thisStream = static_cast<_tcp*>(stream);
}
Well, the static_cast<> actually requires your _tcp class inherits from uv_stream_t
class _tcp : public uv_stream_t {
// ...
};
To extend on your comment
"Could you please explain to me why does uv_listen expects a static function? Is this the behavior for all function pointer parameters?"
There's a difference made between class member function pointers, that need to be bound to a class instance for calling, and plain function pointers, that work for any function definition.
Why uv_listen() expects a plain function pointer, is hard to tell. May be because it's a native C-API (I actually don't know it), or for sake of flexibility.
NOTE: You should not use leading underscores for any symbols (as in class _tcp)!
void listen_uv_listen_uv_connection_cb(uv_stream_t* stream, int status) {
printf("NEW CONNECTION\n");
}; <<<<<remove ;
There should be no semicolon at the end of function definition.
And you should write constructor/copy ctr/assign operator for this class.
I want to pass a class object into a method of other class through a thread call, I tried but got the error can any one help me on this.please.
struct sample{
int status;
std::vector <std::string> a_row;
size_t column_count;
std::vector <std::string> column;
};
class sess {
public:
int a;
sess(int);
sess();
};
class Gen {
private:
static Gen* gen_obj;
public:
static bool Gen_InstanceFlag;
static Gen* GetInstance();
sample addition(sess);
};
/* End of Header File */
/* Beginning of cpp File */
include"Class_thread_mixing.h"
bool Gen::Gen_InstanceFlag=false;
Gen* Gen::GetInstance(){
if(!Gen::Gen_InstanceFlag){
Gen::gen_obj = new Gen();
Gen::Gen_InstanceFlag= true;
return gen_obj;
}
else {
return gen_obj;
}
}
sample addition(sess ses_obj){
sample sam;
sam.a_row.push_back("success");
sam.column.push_back("result");
sam.column_count=1;
sam.status=ses_obj.a;
return sam;
}
int main(int argc, char* argv[])
{
HANDLE myhandleA;
Gen* gen=Gen::GetInstance();
sess ses_obj(10);
myhandleA=(HANDLE)_beginthreadex(0, 0, gen->addition(ses_obj),(void*)0, 0, 0);
WaitForSingleObject(myhandleA, INFINITE);
CloseHandle(myhandleA);
getchar();
return 0;
}
This is my code and I am getting an error like "error C2665: '_beginthreadex' : none of the 2 overloads could convert all the argument types"
Can any one suggest me who can I pass the object of sess to a function in a thread call and how can I get the results from the thread.
Thanks for your answers..
s there any option such that I can call the function directly in the thread without calling a standalone thread function, like I mentioned in my code [(HANDLE)_beginthreadex(0, 0, gen->addition(ses_obj),(void*)0, 0, 0) ]
I need to call addition method in the thread can any body help me on this.
The problem here is that instead of passing a function to the called by _beginthreadex, you are actually calling that function with an argument, causing the _beginthreadex function to be called with the return value from Gen::addition. This structure is if course not a function, and so the compiler complains.
The solution to this is not straightforward though. First of all because a stand-alone function (as required by _beginthreadex is not the same as a class member function. The reason being that all class member functions actually have a "zeroeth" hidden argument, and that is an instance of the class that becomes the this pointer that can be used inside member functions.
The best solution is probably to create a stand-alone function, which takes as argument a pointer to a structure, and the structure contains the object instance, and the argument to the actual member function.
Something like this:
struct call_data
{
sess sess_obj;
Gen* gen_obj;
};
static void thread_function(void* data)
{
call_data *call = reinterpret_cast<call_data*>(data);
// Do the actual member function call
call->gen_obj->addition(call->sess_obj);
}
int main()
{
...
call_data call = { ses_obj, gen };
myhandleA=(HANDLE)_beginthreadex(0, 0, thread_function, &call, 0, 0);
...
}
Entry point for thread can't be a class method. it has to be static or at global scope.
You need to define a static method like this
static unsigned ThreadEntry(void* arg)
{
sess *p = (sess*)arg;
Gen::GetInstance()->addition(*p);
}
and run the thread like this:
sess ses_obj(10);
myhandleA=(HANDLE)_beginthreadex(0, 0, ThreadEntry,(void*)&ses_obj, 0, 0);
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'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.