Hello Everyone ,
I'am new to OOP and QT and i'm trying to write a simple chat program (client , server) with winsockets.
I Have an error which i don't seem to understand :

this is my code so far :

#include "pmessenger.h"
#include "ui_pmessenger.h"
#include <QMessageBox>
#include <winsock2.h>
SOCKET s;
PMessenger::PMessenger(QWidget *parent) : QMainWindow(parent), ui(new Ui::PMessenger)
{
    ui->setupUi(this);
    WSADATA wsadata;
    if(WSAStartup(MAKEWORD(2,2),&wsadata)!=0)
    {
         QMessageBox::critical(this,"Error","Winsock Startup Failed",0,0);
         this->close();
    }
    s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if(s==INVALID_SOCKET)
    {
          QMessageBox::critical(this,"Error","Socket Creation Faild",0,0);
          WSACleanup();
          this->close();
    }
    SOCKADDR_IN server;
    server.sin_family = AF_INET;
    server.sin_port = htons(7676);
    server.sin_addr.s_addr = inet_addr("my ip is here :D");
    if(::connect(s,(sockaddr*)&server,sizeof(server))!=0)
    {
          QMessageBox::critical(this,"Error","Can't Connect",0,0);
          WSACleanup();
          this->close();
    }
    CreateThread(NULL,0,ServerMsgThread,(LPVOID)s,0,0); // the problem is in this line :(
}

PMessenger::~PMessenger()
{
    delete ui;
}

void PMessenger::on_pushButton_clicked()
{
    QString msg = ui->plainTextEdit_2->toPlainText();
    send(s,(const char *)msg.data(),4096,0);
}

void PMessenger::AddMessege(char msg[4096])
{
    ui->plainTextEdit->appendPlainText(msg);
}

DWORD PMessenger::ServerMsgThread(LPVOID pParam)
{
      SOCKET Cs = (SOCKET) pParam;
      char data[4096];
      while(1)
      {
           if(recv(Cs,data,1024,0)>0)
               AddMessege(data);
      }
      return 0;
}

I Get the following error :

..\PMessenger\pmessenger.cpp:32: error: argument of type 'DWORD (PMessenger:: )(void*)' does not match 'DWORD (*)(void*)'

Any help would be greatly appreciated (i really don't want to move to wxWidgets because of that error)

Thanks

Edited 6 Years Ago by medopunsher: n/a

CreateThread doesn't take a pointer to a class's method, let's read the error message together:
Your argument type: 'DWORD (PMessenger:: )(void*)'
Expected arg type: 'DWORD (*)(void*)'

So CreateThread is expecting a pointer to a function that returns a DWORD and takes void* as argument. There are several ways to 'beat' this problem, because you cannot simply cast your function to a DWORD (*)(void*).

You can use a 3rd party library like 'boost', which allows you to use pointers to member functions to start a thread.
You can create a small 'wrapper' function like this:

DWORD start_ServerMsgThread( LPVOID param )
{
   PMessenger* pMsg = static_cast<PMessenger*>( param );
   pMsg->ServerMsgThread();
}

And start the thread like:

CreateThread( NULL, 0, &start_ServerMsgThread, static_cast<LPVOID>(this), 0, 0);

You hand over the SOCKET to ServerMsgThread, but you can just store this as a private member variable and access it from ServerMsgThread.
If you don't want to do this, you can create a structure with 2 members:

struct StartThreadStruct {
  SOCKET s;
  PMessenger* pMsg;
};

Allocate this, hand it over to CreateThread and from start_ServerMsgThread pass it to ServerMsgThread and access the SOCKET from there.

I hope that helps.

Edited 6 Years Ago by thelamb: n/a

why using Windows thing in QT, I mean QT is designed to be Xplatform and using windoish stuffs limits the very purpose. If you plan to use it in windows then go for Win32 API, or stay away from windowing and do it QT way :)

Having said so, I suggest Zetcode QT tutorial as one of Good start

@thelamb thanks a lot man , you really made my day , solved :D

@evstevemd you know what , you make a lot of sense , i mean it was very stupid of me to learn an Xplatform gui library then use windows stuff in the rest of the program :D
Oh and thanks for the tutorial seems great but do you know a QT network tutorial , coz the only i found was in german and the links were dead , Thanks. :)

@thelamb , i get an error when i tried to implement your idea at this line :
CreateThread(NULL,0,&ServerMsgThread,static_cast<LPVOID>(w),0,0);
Error : invalid static_cast from type 'PMessenger' to type 'void*'
:S

That's my code so far ,

#include <QtGui/QApplication>
#include "pmessenger.h"
#include "ui_pmessenger.h"
#include<winsock2.h>
#include<QMessageBox>
DWORD WINAPI ServerMsgThread(LPVOID pParam);
SOCKET s;
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    PMessenger w;
    w.show();
    WSADATA wsadata;
    if(WSAStartup(MAKEWORD(2,2),&wsadata)!=0)
    {
         QMessageBox::critical(0,"Error","Winsock Startup Failed",0,0);
         return 0;
    }
    s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if(s==INVALID_SOCKET)
    {
          QMessageBox::critical(0,"Error","Socket Creation Faild",0,0);
          WSACleanup();
          return 0;
    }
    SOCKADDR_IN server;
    server.sin_family = AF_INET;
    server.sin_port = htons(7676);
    server.sin_addr.s_addr = inet_addr("41.238.115.48");
    if(::connect(s,(sockaddr*)&server,sizeof(server))!=0)
    {
          QMessageBox::critical(0,"Error","Can't Connect",0,0);
          WSACleanup();
          return 0;
    }
    CreateThread(NULL,0,&ServerMsgThread,static_cast<LPVOID>(w),0,0);
    return a.exec();
}

DWORD WINAPI ServerMsgThread(LPVOID pParam)
{
      PMessenger *ww = static_cast<PMessenger*>(pParam);
      char data[4096];
      while(1)
      {
           if(recv(s,data,1024,0)>0)
               ww->AddMessege(data);
      }
      return 0;
}

void PMessenger::on_pushButton_clicked()
{
    QString msg =  ui->plainTextEdit_2->toPlainText();
    send(s,(const char *)msg.data(),4096,0);
}

:D I Already did , and nearly finished the program in QT Sockets instead of WinSockets
Thanks a lot man.

This question has already been answered. Start a new discussion instead.