I'm developing a simple instant-messaging software on Ubuntu 12.10, it's client requires GUI.
In the main window of the client, i need to create a thread to keep listening messages received from the server.
Here is the error message:
main.cpp:-1: In function 'int main(int, char**)':
main.cpp:27: error: invalid conversion from 'void*' to 'void* (*)(void*)' [-fpermissive]
/usr/include/pthread.h:225: error: initializing argument 3 of 'int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)' [-fpermissive]
In the maininterface.h:
Class MainInterface: public QWidget
{
public:
explicit MainInterface(QWidget *parent = 0);
~MainInterface();
void* ServerMSGWatch(void *threadArgs=NULL); // function run in the new thread
};
It's definition in maininterface.cpp is:
void* MainInterface::ServerMSGWatch(void *threadArgs)
{
pthread_detach(pthread_self());
char arrServerMSGRecv[SERVER_MSG_MAX_SIZE + 1];
while(1){
recv(Login::sockClnt, arrServerMSGRecv, SERVER_MSG_MAX_SIZE+1, 0);
Handle_Server_MSG(arrServerMSGRecv);
memset(arrServerMSGRecv, 0, SERVER_MSG_MAX_SIZE+1);
}
return NULL;
}
in main.cpp:
MainInterface mWindow;
mWindow.show();
pthread_t pthreadID;
pthread_create(&pthreadID, NULL, mWindow.ServerMSGWatch(), NULL);
and in this question, i figured out that maybe there's something wrong with using a C++ compiler to compile c code.
so i tried to add a 'c_pthread.h':
#ifndef C_PTHREAD_H
#define C_PTHREAD_H
#ifdef __cplusplus
extern "C" {
#endif
void* ServerMSGWatch(void *threadArgs=NULL);
void Handle_Server_MSG(char *arrServerMSGRecv);
#ifdef __cplusplus
}
#endif
#endif // C_PTHREAD_H
and c_pthread.cpp:
void* ServerMSGWatch(void *threadArgs=NULL)
{
//definition
}
void Handle_Server_MSG(char *arrServerMSGRecv)
{
//definition
}
then invoke it in main.cpp:
#include "c_pthread.h"
pthread_t pthreadID;
pthread_create(&pthreadID, NULL, ServerMSGWatch(), NULL);
but i still got the same error.
PS: sorry about some malapropisms.
You have two problems: The first is that you call the function instead of passing it. The other is more subtle, and is that you can't use a non-static class member function as a thread function.
The reason for the last problem is because non-static member function have a hidden first argument that is the this pointer.
In this case you can solve it by adding a static member function, and pass a pointer to the object as argument to the thread function. Then the static function calls the actual function in the object:
class MainInterface: public QWidget
{
public:
...
static void* StaticServerMSGWatch(void* arg)
{
reinterpret_cast<MainInterface*>(arg)->ServerMSGWatch();
return nullptr;
}
void ServerMSGWatch(); // function run in the new thread
};
...
pthread_create(&pthreadID, NULL, &MainInterface::StaticServerMSGWatch, &mWindow);
If you have a C++11 capable compiler and library, you could use std::thread instead:
std::thread myThread(&MainInterface::ServerMSGWatch, &mWindow);
As you see, you no longer need the static member function.
You're using Qt, so I strongly suggest using QThread. This will guarantee compatibility and the interop with the rest of your program will be better.
That being said, you need to pass a function pointer to pthread_create, and a member function pointer is not a function pointer: either make it static or make it a freestanding function.
In C++11, there's no need to muck around with low-level system libraries:
std::thread thread([&]{mWindow.ServerMSGWatch();});
If you're stuck with a historic version of C++ then, since you say you're using Qt, you might consider its thread class QThread.
If you're stuck with pthreads then, being a C API, it knows nothing about member functions, so you'll need a non-member, or static member function. (Strictly speaking, you should only use a non-member function declared extern "C", but in practice C++ functions will work on any sensible implementation).
So you'll need a wrapper function to call the member function:
void * CallServerMSGWatch(void * p) {
return static_cast<MainInterface*>(p)->ServerMSGWatch();
}
and tell pthread_create to pass a suitable pointer through to this:
pthread_create(&pthreadID, NULL, CallServerMSGWatch, &mWindow);
mWindow.ServerMSGWatch() is a function call.
mWindow.ServerMSGWatch is a function pointer.
Related
I am trying to link to an external library in my QT application. The external library has a header file with the following relevant code I'm trying to call:
extern VGRABDEVICE_API bool V_AssignFrameSizeCallback(IGrabChannel* pChannel, void* pFunc);
In the demo C++ program provided, which has no problems compiling, the following relevant code is:
// in main.cpp
void _stdcall MyFrameSizeCallback(T x) {
do_stuff;
}
int main(int argc, char* argv[]) {
IGrabChannel* pChannel0 = something;
V_AssignFrameSizeCallback(pChannel0, MyFrameSizeCallback);
}
I am trying to incorporate this code into my QT application, but getting problems. In my mainwindow.cpp file:
void _stdcall MainWindow::MyFrameSizeCallback(T x) {
do_stuff;
}
void MainWindow::someFunction() {
IGrabChannel* pChannel0 = something;
V_AssignFrameSizeCallback(pChannel0, &MainWindow::MyFrameSizeCallback);
}
The error I'm getting is:
error: C2664: 'bool V_AssignFrameSizeCallback(IGrabChannel *,void *)' :
cannot convert argument 2 from 'void (__cdecl MainWindow::* )(T)' to 'void *'
There is no context in which this conversion is possible
What do I need to do? Thanks.
You have two problems. First, void* is a data pointer, not a function pointer. According to the C++ standard, casting between the two is not expected to work. Some platforms provide a stronger guarantee... for example Windows GetProcAddress and *nix dlsym mix the two.
Next, your &MainWindow::MyFrameSizeCallback is not a function pointer, it is a pointer-to-member-function. Calling it requires a MainWindow object, which the external library doesn't know anything about.
You need to provide an ordinary function, not a member function, to the library. If you have some way to get ahold of the MainWindow* object pointer, you can then call its member function to do the real work. Sometimes the library provides a "context" parameter which is passed to your callback; that's a great place to put the object pointer. Otherwise, you'll need to store your MainWindow* in a global variable. Easy if you have just one, while if you have more than one you might go with std::map<IGrabChannel*, MainWindow*>.
Code:
MainWindow* MainWindow::the_window;
void MainWindow::MyFrameSizeCallback(T x)
{
do_stuff;
}
void _stdcall MyFrameSizeCallbackShim(T x)
{
MainWindow::the_window->MyFrameSizeCallback(x);
}
void MainWindow::someFunction()
{
IGrabChannel* pChannel0 = something;
the_window = this;
V_AssignFrameSizeCallback(pChannel0, &MyFrameSizeCallbackShim);
}
If the parameter x isn't an IGrabChannel, change the map datatype and insertion logic accordingly. If the parameter x isn't some sort of unique predictable identifier, you may be limited to only doing callbacks to one MainWindow instance.
Trying to write some simple multithreaded server program and got that error recently:
Server.cpp:64:64: error: argument of type ‘void* (Server::)(void*)’ does not match ‘void* (*)(void*)
Here is some lines from my code:
Header file:
class Server
{
public:
void establishConnection(const char * );
...
private:
void *listening(void *);
void *acceptingConnection(void *);
pthread_attr_t attrr;
}
cpp file:
void Server:: establishConnection(const char *port_number )
{
...
pthread_create(&listn, &attrr, Server::listening, (void*)socketfd);//pthread_t listn, socketfd is a socket destricptor(int)
pthread_join(listn, NULL);
}
void* Server::listening(void *arg)
{
int socketfd = (int)arg;
...
}
Normally, if I define thread function prototypes in the cpp file instead of header file, it works properly(without Server:: definition of course) Tried few other things like (void*)Server::listening, listening, (void*)listening but still didnt work. Could you enlighten me? How to pass the method parameter to listening method?
Secondly, I am learning c++ currently(already know C), is it true to use some C methods, char* arrays instead of strings, header files in the c++ program? Such as string.h, stdlib.h, pthread.h?
You need to create a wrapper function for pthread_create(), and from there call into your class method.
class Server
{
...
private:
int sock;
};
extern "C" void * server_listening (void *arg) {
Server *s = static_cast<Server *>(arg);
return s->listening();
}
void Server:: establishConnection(const char *port_number )
{
...
this->sock = socketfd;
pthread_create(&listn, &attrr, server_listening, this);
pthread_join(listn, NULL);
}
The extern "C" linkage on the wrapper function is in place since pthread_create() is a C function, and expects a function pointer with C linkage. This is important if on your system the C ABI and the C++ ABI are not the same. A static method of a class can only have C++ linkage.
You can just read the error message:
type ‘void* (Server::)(void*)’ does not match ‘void* (*)(void*)‘
Because Server::listening is a non-static member function of Server, and a pointer non-static member function cannot possibly be converted to a pointer-to-non-member-function.
You have to make your Server::listening function static, or write a stand-alone function outside the Server class.
I'm using Xcode and C++ to make a simple game.
The problem is the following code:
#include <pthread.h>
void *draw(void *pt) {
// ...
}
void *input(void *pt) {
// ....
}
void Game::create_threads(void) {
pthread_t draw_t, input_t;
pthread_create(&draw_t, NULL, &Game::draw, NULL); // Error
pthread_create(&input_t, NULL, &Game::draw, NULL); // Error
// ...
}
But Xcode gives me the error: "No matching function call to 'pthread_create'". I haven't an idea 'cause of I've included pthread.h already.
What's wrong?
Thanks!
As Ken states, the function passed as the thread callback must be a (void*)(*)(void*) type function.
You can still include this function as a class function, but it must be declared static. You'll need a different one for each thread type (e.g. draw), potentially.
For example:
class Game {
protected:
void draw(void);
static void* game_draw_thread_callback(void*);
};
// and in your .cpp file...
void Game::create_threads(void) {
// pass the Game instance as the thread callback's user data
pthread_create(&draw_t, NULL, Game::game_draw_thread_callback, this);
}
static void* Game::game_draw_thread_callback(void *game_ptr) {
// I'm a C programmer, sorry for the C cast.
Game * game = (Game*)game_ptr;
// run the method that does the actual drawing,
// but now, you're in a thread!
game->draw();
}
compilation of threads using pthread is done by providing options -pthread.
Such as compiling abc.cpp would require you to compile like g++ -pthread abc.cpp else would
give you an error like undefined reference topthread_create collect2: ld returned 1 exit status` . There must be some similar way to provide pthread option.
You're passing a member function pointer (i.e. &Game::draw) where a pure function pointer is required. You need to make the function a class static function.
Edited to add: if you need to invoke member functions (which is likely) you need to make a class static function which interprets its parameter as a Game* and then invoke member functions on that. Then, pass this as the last parameter of pthread_create().
I have this C++ code, where i try to create a pthread, and i got 4 errors:
Can anyone please help?
Thanks in advance.
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
static void* func(void*);
class Test
{
public:
pthread_t *threadId;
pthread_create(threadId, NULL, func, NULL);
};
static void* func(void *arg)
{
printf("Thread function called\n");
}
int main()
{
Test();
}
Compiling:
# g++ simplepThread.cc -lpthread
simplepThread.cc:11: error: ‘threadId’ is not a type
simplepThread.cc:11: error: expected identifier before ‘__null’
simplepThread.cc:11: error: expected ‘,’ or ‘...’ before ‘__null’
simplepThread.cc:11: error: ISO C++ forbids declaration of ‘pthread_create’ with no type
If i use the thread function as a "C" linkage:
extern "C" void* func(void *arg)
{
printf("Thread function called\n");
}
Error faced is:
simplepThread.cc:7: error: previous declaration of ‘void* func(void*)’ with ‘C++’ linkage
simplepThread.cc:15: error: conflicts with new declaration with ‘C’ linkage
You can't call functions in class declaration. In class declaration you can only declare (and possibly define) its members. And
pthread_create(threadId, NULL, func, NULL);
is not a valid member function definition.
The whole class Test seems to be redundant.
static void* func(void *arg)
{
printf("Thread function called\n");
}
int main()
{
pthread_t threadId;
pthread_create(&threadId, NULL, func, NULL);
}
Should work fine.
I fixed also another problem - you tried to pass an uninitialized pointer (threadId) to a function that expects a variable address.
UPDATE
About the linkage - you have a prototype with default (C++ linkage)
void* func(void *arg);
And definition with C linkage
extern "C"
{
void* func(void *arg)
{
....
}
}
So they conflict. change prototype to
extern "C"
{
void* func(void *arg);
}
And it will be OK
There are a number of issues with your code. First of all, you need to declare a constructor function for the Test class, and given how you used the code, I would put the pthread_create() call inside the constructor. Secondly, while pthread_create() takes as its first argument a pthread_t* argument, this means that that argument is being used as an output parameter and the pointer should point to the actual memory/variable where the thread ID for the newly created thread will be placed.
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
static void* func(void*);
class Test
{
public:
pthread_t threadId;
Test() {
pthread_create(&threadId, NULL, func, NULL);
}
};
static void* func(void *arg)
{
printf("Thread function called\n");
}
int main()
{
Test();
}
In general when you are doing multi-threaded code, you also want to ensure that the threads are destroyed when you are finished with them, or keep track of when they die on their own. For example, if you create a "worker" thread that will be used to process work in the background asynchronously, then you will often want to have a mutex-protected queue for the main thread to pass work to the worker thread. You would often also want some semaphore or other "safe" signaling system to cause the worker thread to die safely when the program wants to exit, with a back-signaling mechanism so the main thread knows when the worker has died and it is now safe to clean up the shared data structures. (i.e., putting a piece of work in the job queue that simply says "die", and having the worker reply "dying" before exiting)
Implementing correct multi-threaded code is non-trivial, and you have to worry about a wide range of issues, such as deadlock and race conditions, that simply do not occur with single-threaded code. I strongly recommend that you read about, and ensure that you fully understand, these and other topics.
Greetings,
My project structure is as follows:
\- base (C static library)
callbacks.h
callbacks.c
paint_node.c
.
.
* libBase.a
\-app (C++ application)
main.cpp
In C library 'base' , I have declared global-function-pointer as:
in singleheader file
callbacks.h
#ifndef CALLBACKS_H_
#define CALLBACKS_H_
extern void (*putPixelCallBack)();
extern void (*putImageCallBack)();
#endif /* CALLBACKS_H_ */
in single C file they are initialized as
callbacks.c
#include "callbacks.h"
void (*putPixelCallBack)();
void (*putImageCallBack)();
Other C files access this callback-functions as:
paint_node.c
#include "callbacks.h"
void paint_node(node *node,int index){
//Call callbackfunction
.
.
putPixelCallBack(node->x,node->y,index);
}
I compile these C files and generate a static library 'libBase.a'
Then in C++ application,
I want to assign C++ instance method to this global function-pointer:
I did something like follows :
in Sacm.cpp file
#include "Sacm.h"
extern void (*putPixelCallBack)();
extern void (*putImageCallBack)();
void Sacm::doDetection()
{
putPixelCallBack=(void(*)())&paintPixel;
//call somefunctions in 'libBase' C library
}
void Sacm::paintPixel(int x,int y,int index)
{
qpainter.begin(this);
qpainter.drawPoint(x,y);
qpainter.end();
}
But when compiling it gives the error:
sacmtest.cpp: In member function ‘void
Sacm::doDetection()’:
sacmtest.cpp:113: error: ISO C++
forbids taking the address of an
unqualified or parenthesized
non-static member function to form a
pointer to member function. Say
‘&Sacm::paintPixel’ sacmtest.cpp:113:
error: converting from ‘void
(Sacm::)(int, int, int)’ to ‘void
()()’
Any tips?
This is answered in the C++ FAQ, [1]. This doesn't work, because the pointer isn't associated with a particular object instance. The solution is given there too, create a global function that uses a particular object:
Sacm* sacm_global;
void sacm_global_paintPixel(int x,int y,int index)
{
sacm_global->paintPixel(x, y, index);
}
void Sacm::doDetection()
{
putPixelCallBack = &sacm_global_paintPixel;
//call somefunctions in 'libBase' C library
}
You have to somehow setup the global variable properly.
You cannot convert an instance method pointer to a normal function pointer. A workaround is to use another global variable to hold the instance and a global wrapper function that is used as the callback and then in turn calls the instance method:
Sacm *callbackSacm;
extern "C" // since it sounds like it's called from a C library
void call_paintPixel(int x, int y, int index) {
callbackSacm->paintPixel(x, y, index);
}
void Sacm::doDetection() {
callbackSacm = this;
putPixelCallBack = call_paintPixel;
}
You can alternatively use a static member function. The address of a static member function can be taken and assigned to a regular function pointer, because no this pointer is implicitly passed to it -- under the hood, these functions operate just like regular non-member functions. But they have advantages over non-member functions:
A static method still has access to the private and protected members of any object of its class type.
A static method can be private or protected so access to it can be controlled.
Using a static method lets you and group functionality inside the class, where it belongs.