0

This is mine base class

class IDialysisConnector
    {
    public:
    HANDLE threadHandle_;   
    virtual int ConnectToMachine();  //This will make socket connection with the machine.
    virtual void WINAPI ServerConnectThread(LPVOID lpdwThreadParam)=0;
    };

Another class

class A:public IDialysisConnector
{

int ConnectToMachine()
{

    int conResult,iResult;;
    struct addrinfo           *result = NULL,*ptr = NULL;

    u_long iMode = 0;
    DWORD nTimeout = 5000; // 5 seconds
    int port=22;
    WSADATA wsaData;

    // Initialize Winsock

    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) 
    {
        printf("WSAStartup failed with error: %d\n", iResult);

    }

    ZeroMemory( &addr_, sizeof(addr_) );
    addr_.ai_family = AF_UNSPEC;
    addr_.ai_socktype = SOCK_STREAM;
    addr_.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    conResult = getaddrinfo("192.168.15.168", (PCSTR)22, &addr_, &result);
    if ( conResult != 0 ) {
        printf("getaddrinfo failed with error: %d\n", conResult);
        WSACleanup();
        return 1;
    }

    // Attempt to connect to an address until one succeeds
    for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {

        // Create a SOCKET for connecting to server
        sock_ = socket(ptr->ai_family, ptr->ai_socktype, 
            ptr->ai_protocol);
        if (sock_ == INVALID_SOCKET) {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }
            conResult = ioctlsocket(sock_, FIONBIO, &iMode);
        if (conResult != NO_ERROR)
            printf("ioctlsocket failed with error: %ld\n", conResult);


        conResult = setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, (const char*)&nTimeout, sizeof(DWORD));
        if (conResult != NO_ERROR)
        {
            printf("\nSetsocopt fail with error :%d\n",WSAGetLastError());

            return 0;
        }


        // Connect to server.
        conResult = connect(sock_, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (conResult == SOCKET_ERROR) {
            closesocket(sock_);
            sock_ = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    if (sock_ == INVALID_SOCKET) {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return 1;
    }
    DWORD dwThreadId;
    //threadHandle_=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ServerConnectThread,this,0,&dwThreadId);
        threadHandle_=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc,this,0,&dwThreadId);
   void WINAPI IDialysisConnector::ServerConnectThread(LPVOID lpdwThreadParam)
    {
SOCKET ThreadSocket = INVALID_SOCKET;
    ThreadSocket=(SOCKET)lpdwThreadParam;
    while(1)
    {
        SendRequest(ThreadSocket);
        ReceiveResponse(ThreadSocket);
        Sleep(10000);
    }
        }

static UINT ThreadFunc(LPVOID param) {
IDialysisConnector* obj = (IDialysisConnector*)param;
obj->ServerConnectThread(); // call the member function
// to do the work in our new thread }

}

}

I did like this too but same error

threadHandle_=CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)IDialysisConnector::ServerConnectThread,(LPVOID)sock_,0,&dwThreadId);

I am getting an error that is

" error C2440: 'type cast' : cannot convert from 'overloaded-function' to 'LPTHREAD_START_ROUTINE'"
Dany
  • 2,034
  • 8
  • 34
  • 54
  • 1
    One of your problems is that you have a function nested directly inside a function. That isn't legal. – Ben Voigt Oct 11 '12 at 13:46
  • 1
    It also scares me that an inexperienced programmer is working on what appears to be medical software. – Ben Voigt Oct 11 '12 at 13:47
  • @BenVoigt, good catch, I was about to point that out, that's a major syntax error. – Brady Oct 11 '12 at 13:47
  • @BenVoigt Good point sir but is an sample and you are correct am not experienced – Dany Oct 11 '12 at 14:04
  • You updated the code but you *still* have a function nested directly inside another function. The compiler won't be able to make any sense of your code, I'm surprised it gave you as useful an error message as this. – Ben Voigt Oct 11 '12 at 15:28

2 Answers2

4

No, CreateThread expects a plain function pointer, which is quite different from a pointer to a non-static C++ member function.

You have to create a normal function for the function you give CreateThread. That function can act as a trampoline back to the C++ world, e.g.

static UINT WINAPI ThreadFunc(LPVOID param)
{
   IDialysisConnector* obj = (IDialysisConnector*)param;
   obj->ServerConnectThread(); // call the member function
                               // to do the work in our new thread
}

Then your ConnectToMachine becomes:

int ConnectToMachine()
{
    DWORD dwThreadId;
    //give 'this' as the thread param to ThreadFunc
    threadHandle_=CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)ThreadFunc,(LPVOID)this,0,&dwThreadId);
}
nos
  • 223,662
  • 58
  • 417
  • 506
  • A static class function works OK whenever I've tried it. Passing 'this' as an explicit parameter then allows the calling of member functions. – Martin James Oct 11 '12 at 13:48
  • @nos thanks for the answer sir i updated my code as you can see i am expecting a socket as paramer in ServerConnectThread that i pass to my send and recv function,can you please update your solution accordingly – Dany Oct 11 '12 at 14:03
  • 1
    @Dany: Put the socket handle in a member variable. Once you pass the `this` pointer to the function, you also have access to all member variables. – Ben Voigt Oct 11 '12 at 15:29
  • @BenVoigt i also got the same problem i have declare SOCKET sock_ as an public member of the class,now how can i access the socket i mean how to give to ServerConnectThread() – Harry Oct 11 '12 at 17:46
  • @Harry: The way nos showed you gives the entire class instance to `ServerConnectThread` (it's a non-static member function). So use the `this` pointer from inside, maybe implicitly. – Ben Voigt Oct 11 '12 at 22:40
  • @Harry The code I showed ends up calling the member function `obj->ServerConnectThread()`, so inside the `ServerConnectThread()` function you simply do `this->my_socket`. And ofcourse, `this` isn't even needed, so if you did make your socket a member variable, you just access it as `my_socket` – nos Oct 11 '12 at 23:26
  • @Dany Your edited code which you claim fails is wrong, you have this code: `CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)IDialysisConnector::ServerConnectThread,(LPVOID)sock_,0,&dwThreadId);` Which is not what I posted. You _have_ to place `sock_` in a member variable of your `IDIalysisConnectior` class, and you have to do : `CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)ThreadFunc,(LPVOID)this,0,&dwThreadId);` – nos Oct 11 '12 at 23:29
0

A non-static member function can only be called on an object. That's why its type is pointer-to-member-function and not pointer-to-function. CreateThread expects a pointer to function, and you can't give it a pointer to member function instead.

Some folks will advise you to make it a static member function; that's usually okay, but I'm skeptical of design changes that are made only to make implementation easier. If it's a non-static member function, then, presumably, there's a reason for it to be a non-static member function.

You can write a function that does the appropriate call:

void callback(void*p) {
    (IDialysisConnector*p)->ServerConnectThread();
}

and pass that as the thread function, with the address of the appropriate object as the data pointer in the call to CreateThread.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • Yes, but this callback helper should probably be the non-static member function you just expressed skepticism about, and it should have a useful name such as `ServerConnectThreadShim`. – Ben Voigt Oct 11 '12 at 13:48
  • @BenVoigt - I did **not** express skepticism about a using a static member function. I expressed skepticism about **advising** someone to change a non-static member function into a static one just so it could be passed to `CreateThread` without knowing details of the design. – Pete Becker Oct 11 '12 at 13:54