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.
Related
I am compiling with g ++ an application that calls some functions defined in a "C" library.
Some of the functions that I need to call are defined as static in the original ".c" file (I know that when a function is defined static it is so that it is not called from outside of that file, but despite that, I need to call them from outside of the same).
I am going to execute them from outside that file using pointers to functions and to see how they work, I have prepared this example, where I want to execute in file_2.c the static functions fun5 and fun6 defined in file_1.c
file_1.h
--------
#ifndef FILE_1_H
#define FILE_1_H
int (*getPtrFun6(void*))(int,char,char*);
#endif
file_1.c
--------
#include <stdio.h>
int(*ptr_fun5)(int,int);
static int fun5(int p1, int p2)
{
printf("fun5 called.\n");
ptr_fun5 = &fun5;
return p1 + p2;
}
static int fun6(int p1, char p2, char* p3)
{
printf("fun6 called with p1 = %d, p2 = %c, p3 = %s.\n", p1, p2, p3);
return p1;
}
int (*getPtrFun6(void*))(int,char,char*)
{
return fun6;
}
file_2.c
--------
#include <stdio.h>
#include <cstring>
#include "file_1.h"
extern int(*ptr_fun5)(int,int);
extern int(*ptr_fun6)(int,char,char*);
int main(void)
{
int returnValue = 0;
// To run fun5
returnValue = (ptr_fun5)(15, 32);
printf ("Returns %d\n", returnValue);
// To run fun6
char myString[50];
memset(myString,0,50);
strncpy(myString,"THIS IS OK",10);
ptr_fun6 = getPtrFun6();
returnValue = (ptr_fun6)(32, 'v', myString);
printf ("Returns %d\n", returnValue);
return 0;
}
I compile the program with the command:
g++ file_2.c file_1.c -o static_example
As you can see from the source code, I have tried two different ways to use a pointer to a static function.
If I comment on everything about fun6 in the source code, compile it and run it (just call fun5) I get the error "Segmentation fault".
On the other hand, if I comment on everything related to fun5 in the source code and leave only fun6, when compiling the program, I get these errors:
file_2.c: In function ‘int main()’:
file_2.c:20:25: error: too few arguments to function ‘int (* getPtrFun6(void*))(int, char, char*)’
ptr_fun6 = getPtrFun6();
^
In file included from file_2.c:4:
file_1.h:4:7: note: declared here
int (*getPtrFun6(void*))(int,char,char*);
^~~~~~~~~~
I have looked at various forums and tutorials on the web and I don't see what the error is, so I would need some help on the correct way to use the pointers to fun5 and fun6.
(just call fun5) I get the error "Segmentation fault".
Because fun5 is uninitialized, it doesn't point anywhere.
when compiling the program, I get these errors: ... error: too few arguments to function
So why did you declare it to take a void* as parameter? If you don't want that, then it should be void.
General advise:
Get rid of global variables with extern.
Use typedef whenever dealing with function pointers, so that the code can be read by humans. Evidentally, int (*getPtrFun6(void*))(int,char,char*) isn't readable even by yourself.
int (*getPtrFun6(void*))(int,char,char*);
Confusing syntax is leading to wrong prototype and declaration.
The easy to read way (function pointers are same as "normal" pointers):
typedef int fun6type(int, char, char *);
fun6type *getPtrFun6(void);
fun6type *getPtrFun6(void)
{
return fun6;
}
Hard to read way:
int (*getPtrFun6_1(void))(int, char, char *);
int (*getPtrFun6_1(void))(int, char, char *)
{
return fun6;
}
int foo(void)
{
int (*f)(int, char, char *) = getPtrFun6_1();
return f(1, 'a', "Test");
}
Test it yourself
https://godbolt.org/z/erh63jTc8
If I comment on everything about fun6 in the source code, compile it
and run it (just call fun5) I get the error "Segmentation fault".
Function pointer has to reference a valid function before it is dereferenced (called) as any other pointer. Your one is not initialized and it is not referencing a valid function.
BTW It is rather C code (not C++). In C++ use of function pointers (and generally pointers) should be avoided.
returnValue = (ptr_fun5)(15, 32); does not work because ptr_fun5 is initialized to a null pointer and is not given any other value until the statement ptr_fun5 = &fun5; inside fun5 is executed, which does not happen until fun5 is called.
One way to fix that is to delete int(*ptr_fun5)(int,int); and put int (*ptr_fun5)(int, int) = fun5; after the declaration of fun5. Then it will be initialized to the address of fun5.
Assume that we have a C++ project. We can use a function which defined in a C file in the C++ project through extern "C" keyword. Example:
C code: cfile.c
#include <stdio.h>
void f(void)
{
printf("\n This is a C code\n");
}
Cpp Code: cppfile.cpp
#include <iostream>
extern "C" {
void f();
}
int main(void)
{
f();
return 0;
}
So, can we do that for the opposite case:
Cpp code: cppCode.cpp
struct MyClass
{
virtual void f(const char* text);
void func(const char* text);
};
Can we implement f method and func method in a C file (for instance: cCode.c) ??? Is that possible ? (Just the question for my personal purpose)
You can't do this directly. However, there is a workaround (of sorts). You can have a function with "C" linkage which returns the pointer to the object of the class - presumably dynamically allocated - converted to void*.
Than you can implement functions which would map to functions inside the class, but would take one additional argument - void*, which would be the address obtained from the call to creation function above. They would simply convert this void* to the type of the class and call it's member.
In the end, you'd need a dispose function which would corectly delete the pointer.
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.
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.