0

これは私の基本クラスです

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

別のクラス

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(); //メンバー関数を呼び出して
//新しいスレッドで作業を行います}

}

}

私もこれが好きでしたが、同じエラー

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

エラーが発生しています

" error C2440: 'type cast' : cannot convert from 'overloaded-function' to 'LPTHREAD_START_ROUTINE'"
4

2 に答える 2

3

いいえ、CreateThread は単純な関数ポインターを想定しています。これは、非静的 C++ メンバー関数へのポインターとはまったく異なります。

CreateThread に与える関数に対して通常の関数を作成する必要があります。その関数は、トランポリンとして C++ の世界に戻ることができます。

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

次に、ConnectToMachine は次のようになります。

int ConnectToMachine()
{
    DWORD dwThreadId;
    //give 'this' as the thread param to ThreadFunc
    threadHandle_=CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)ThreadFunc,(LPVOID)this,0,&dwThreadId);
}
于 2012-10-11T13:46:13.660 に答える
0

非静的メンバー関数は、オブジェクトでのみ呼び出すことができます。そのため、その型はpointer-to-member-functionであり、 pointer-to-functionではありません。CreateThread関数へのポインターが必要であり、代わりにメンバー関数へのポインターを与えることはできません。

staticメンバー関数にするようにアドバイスする人もいます。通常は問題ありませんが、実装を容易にするためだけに行われる設計変更には懐疑的です。それが非静的メンバー関数である場合、おそらく、それが非静的メンバー関数である理由があります。

適切な呼び出しを行う関数を書くことができます:

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

への呼び出しで適切なオブジェクトのアドレスをデータ ポインターとして使用して、それをスレッド関数として渡しますCreateThread

于 2012-10-11T13:44:39.737 に答える