Converting a function into the desired form

The question was asked: 6 years 10 months ago   views: 7
1

Trying to create a thread in C++ in linux using pthread. Wrote the class Threads to create threads. Wrote a simple class servers. Both classes are working individually. Then do this:

#ifndef SERVER_H
#define SERVER_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include "Threads.h"

class Server {
public:
 Server(int portnum);
 virtual ~Server();
 void* ThreadFunc(void* arg);

private:
 void InitVars();

 int hSocket, newsockfd, iPort;
 socklen_t clilen;
 char buffer[255];
 struct sockaddr_in serv_addr, cli_addr;
 int n;
 bool ServerRunning;
 Threads* thread;

};

#endif /* SERVER_H */

#include "Server.h"

Server::Server(int portnum) {
InitVars();
 // Create socket
 hSocket = socket(AF_INET, SOCK_STREAM, 0);
 if(hSocket < 0)
 throw "ERROR opening socket";
 iPort = portnum;
 // Clear and setup sockaddr_in
 serv_addr.sin_family was = AF_INET;
 serv_addr.sin_addr.s_addr = INADDR_ANY;
 serv_addr.sin_port = htons(iPort);

 if(bind(hSocket, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0)
 throw "ERROR binding";

 listen(hSocket, 10);
 int i = 1;

 thread = new Threads(&Server::ThreadFunc, &i);
// clilen = sizeof(cli_addr);
// newsockfd = accept(hSocket, (struct sockaddr*) &cli_addr, &clilen);
// if(newsockfd < 0)
// fprintf(stderr,"ERROR on accept");
// 
// n = read(newsockfd, buffer, 255);
// if(n < 0)
// throw "ERROR reading from socket";
// 
// printf("%s\n", buffer);
// 
// n = write(newsockfd, "I got your message", 18);
// if(n < 0)
// throw "ERROR writing to socket";
}

Server::~Server() {
 if(hSocket > 0)
close(hSocket);
 if(newsockfd > 0)
close(newsockfd);
}

void Server::InitVars() {
 ServerRunning = true;
 memset((char*) &serv_addr, 0x00, sizeof(serv_addr));
 memset((char*) &cli_addr, 0x00, sizeof(cli_addr));
 memset(buffer, 0x00, 255);
}

void* Server::ThreadFunc(void* arg) {
 clilen = sizeof(cli_addr);
 newsockfd = accept(hSocket, (struct sockaddr*) &cli_addr, &clilen);
 if(newsockfd < 0)
 fprintf(stderr,"ERROR on accept");
 n = read(newsockfd, buffer, 255);
 if(n < 0)
 throw "ERROR reading from socket";

 printf("%s\n", buffer);

 n = write(newsockfd, "I got your message", 18);
 if(n < 0)
 throw "ERROR writing to socket";
}

I get this error:

Server.cpp:29:49: error: no matching function for call "Threads::Threads(void* (Server::*)(void*), int*)" as the designer described as Threads(void*(*thread_func)(void *), void *__restrict arg);

How to fix?

Here is the code of my threads. I'm just learning to work with threads so do not swear =).

#ifndef THREADS_H
#define THREADS_H
#include <pthread.h>

class Threads {
public:
 Threads(void*(*thread_func)(void *), void *__restrict arg);
 virtual ~Threads();

private:
 pthread_t _thread;

};

#endif /* THREADS_H */

#include "Threads.h"

Threads::Threads(void*(*thread_func)(void *), void *__restrict arg) {
 pthread_create(&_thread, NULL, thread_func, arg);
}

Threads::~Threads() {
}
Asked: sercxjo sercxjo 19-01-2012 в 23:35:23

Answers   2

2

You can fix this:

class Server {
public:
 Server(int portnum);
 virtual ~Server();

private:
 struct ThreadParams {
 Server* s;
 int i;
};
 ThreadParams threadParams;

 static void* ThreadFunc(void* arg);
 void InitVars();

 int hSocket, newsockfd, iPort;
 socklen_t clilen;
 char buffer[255];
 struct sockaddr_in serv_addr, cli_addr;
 int n;
 bool ServerRunning;
 Threads* thread;
};

and further:

...
threadParams.s = this;
threadParams.i = 1;

thread = new Threads(&Server::ThreadFunc, static_cast<void*>(&threadParams));
...
...
void* Server::ThreadFunc(void* arg) {
 ThreadParams* tp = static_cast<ThreadParams*>(arg);
 Server& s = *(tp->s);

 s.clilen = sizeof(s.cli_addr);
 s.newsockfd = accept(s.hSocket, (struct sockaddr*) &s.cli_addr, &s.clilen);
 if(s.newsockfd < 0)
 fprintf(stderr,"ERROR on accept");
 s.n = read(s.newsockfd, s.buffer, 255);
 if(s.n < 0)
 throw "ERROR reading from socket";

 printf("%s\n", s.buffer);

 s.n = write(s.newsockfd, "I got your message", 18);
 if(s.n < 0)
 throw "ERROR writing to socket";
}

But in General, if we write in C++, then you need to use the standard thread class, or if the compiler does not support C++11, take a thread from boost.

Answered: gkuznets gkuznets 20-01-2012 в 11:46:44
2

You have in the constructor a second argument of type void*, but You pass int*. Of course, the compiler will complain. Need to bring one type to another :

thread = new Threads(&Server::ThreadFunc, (void*) &i);

Or, as pointed out by @gkuznets:

thread = new Threads(&Server::ThreadFunc, static_cast<void*> (&i));
Answered: @gkuznets @gkuznets 20-01-2012 в 14:17:35