在Qt和标准c ++中将GUI连接到管道

时间:2013-09-17 13:48:36

标签: c++ multithreading qt visual-c++

我的问题是关于链接Qt和win32应用程序 问题是这样的: 我的同事写了一个使用管道的特殊程序。此管道用于向GUI发送特殊消息。 GUI必须显示这些消息。管道程序里面有一个线程。此线程始终在运行并侦听内部消息。每当收到消息时,它就会创建一个新线程,并且该线程必须通过GUI进行通信并显示消息,然后被杀死(他说必须遵循这个例程)。 这是他使用

的代码
DWORD WINAPI PipeThread( void* pContext )
   {

    BOOL   fConnected = FALSE; 
    DWORD  dwThreadId = 0; 
    HANDLE hPipe = INVALID_HANDLE_VALUE, hThread = NULL; 
    LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\InterfacePipe"); 



    SECURITY_ATTRIBUTES sa;
    sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)malloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
    if (!InitializeSecurityDescriptor(sa.lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION))
    {
        DWORD er = ::GetLastError();
    }
    if (!SetSecurityDescriptorDacl(sa.lpSecurityDescriptor, TRUE, (PACL)0, FALSE))
    {
        DWORD er = ::GetLastError();
    }
    sa.nLength = sizeof sa;
    sa.bInheritHandle = TRUE;

    for (;;) 
    { 
        //_tprintf( TEXT("\nPipe Server: Main thread awaiting client connection on %s\n"), lpszPipename);
        hPipe = CreateNamedPipe( 
            lpszPipename,             // pipe name 
            PIPE_ACCESS_DUPLEX,       // read/write access 
            PIPE_TYPE_MESSAGE |       // message type pipe 
            PIPE_READMODE_MESSAGE |   // message-read mode 
            PIPE_WAIT,                // blocking mode 
            PIPE_UNLIMITED_INSTANCES, // max. instances  
            BUFFER_SIZE,                  // output buffer size 
            BUFFER_SIZE,                  // input buffer size 
            0,                        // client time-out 
            &sa);                    // default security attribute 

        if (hPipe == INVALID_HANDLE_VALUE) 
        {
            //_tprintf(TEXT("CreateNamedPipe failed, GLE=%d.\n"), GetLastError()); 
            return -1;
        }

        // Wait for the client to connect; if it succeeds, 
        // the function returns a nonzero value. If the function
        // returns zero, GetLastError returns ERROR_PIPE_CONNECTED. 

        fConnected = ConnectNamedPipe(hPipe, NULL) ? 
TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); 

        if (fConnected) 
        { 
            // Create a thread for this client. 
            hThread = CreateThread( 
                NULL,              // no security attribute 
                0,                 // default stack size 
                InstanceThread,    // thread proc
                (LPVOID) hPipe,    // thread parameter 
                0,                 // not suspended 
                &dwThreadId);      // returns thread ID 

            if (hThread == NULL) 
            {
                return -1;
            }
            else CloseHandle(hThread); 
        } 
        else 
            // The client could not connect, so close the pipe. 
            CloseHandle(hPipe); 
    } 

    return ERROR_SUCCESS;
}

And the code which uses to display message on MFC dialog is this:
DWORD WINAPI InstanceThread(LPVOID lpvParam)
    // This routine is a thread processing function to read from and reply to a client
    // via the open pipe connection passed from the main loop. Note this allows
    // the main loop to continue executing, potentially creating more threads of
    // of this procedure to run concurrently, depending on the number of incoming
    // client connections.
{ 



    HANDLE hHeap      = GetProcessHeap();
    TCHAR* pchRequest = (TCHAR*)HeapAlloc(hHeap, 0, BUFFER_SIZE*sizeof(TCHAR));
    TCHAR* pchReply   = (TCHAR*)HeapAlloc(hHeap, 0, BUFFER_SIZE*sizeof(TCHAR));

    DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0; 
    BOOL fSuccess = FALSE;
    HANDLE hPipe  = NULL;

    // Do some extra error checking since the app will keep running even if this
    // thread fails.z

    if (lpvParam == NULL)
    {
        if (pchReply != NULL) HeapFree(hHeap, 0, pchReply);
        if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest);
        return (DWORD)-1;
    }

    if (pchRequest == NULL)
    {
        if (pchReply != NULL) HeapFree(hHeap, 0, pchReply);
        return (DWORD)-1;
    }

    if (pchReply == NULL)
    {
        if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest);
        return (DWORD)-1;
    }

    // Print verbose messages. In production code, this should be for debugging only.

    // The thread's parameter is a handle to a pipe object instance. 

    hPipe = (HANDLE) lpvParam; 

    // Loop until done reading
    while (1) 
    { 
        // Read client requests from the pipe. This simplistic code only allows messages
        // up to BUFSIZE characters in length.
        fSuccess = ReadFile( 
            hPipe,        // handle to pipe 
            pchRequest,    // buffer to receive data 
            BUFFER_SIZE*sizeof(TCHAR), // size of buffer 
            &cbBytesRead, // number of bytes read 
            NULL);        // not overlapped I/O 

        if (!fSuccess || cbBytesRead == 0)
        {   
            break;
        }

        MyData* data = new MyData;
        data->client_Param = pchRequest;


        HWND handle = FindWindow(NULL,CStringW("MFCApplication1"));
        PostMessage(handle, WM_YOU_HANVE_DATA, reinterpret_cast<WPARAM>(data) ,NULL);

        // Process the incoming message.
        //GetAnswerToRequest(pchRequest, pchReply, &cbReplyBytes); 

        if (wcscmp(pchRequest,L"msg1")==0)
            StringCchCopy( pchReply, BUFFER_SIZE, TEXT("Hi"));
        else
            StringCchCopy( pchReply, BUFFER_SIZE, TEXT("default echo answer"));

        cbReplyBytes = (lstrlen(pchReply)+1)*sizeof(TCHAR);
        // Write the reply to the pipe. 
        fSuccess = WriteFile( 
            hPipe,        // handle to pipe 
            pchReply,     // buffer to write from 
            cbReplyBytes, // number of bytes to write 
            &cbWritten,   // number of bytes written 
            NULL);        // not overlapped I/O 

        if (!fSuccess || cbReplyBytes != cbWritten)
        {   
            break;
        }
    }

    // Flush the pipe to allow the client to read the pipe's contents 
    // before disconnecting. Then disconnect the pipe, and close the 
    // handle to this pipe instance. 

    FlushFileBuffers(hPipe); 
    DisconnectNamedPipe(hPipe); 
    CloseHandle(hPipe); 

    HeapFree(hHeap, 0, pchRequest);
    HeapFree(hHeap, 0, pchReply);

    return 1;
}

如你所见,他使用的是函数而不是方法。我创建了一个类并推送他的方法并使用信号和插槽来获得目标。 但它崩溃了。原因是createThread方法必须获取函数的名称而不是方法的名称。所以我创建方法作为静态方法,但另一个错误引发。信号和插槽应使用真实对象(在moc文件中,它使用“this”关键字,与此方法不兼容) 我应该如何克服这个问题

PipeCreator::PipeCreator(QObject *parent = 0) :
    QObject(parent)
{
    HANDLE hPipeThread = CreateThread( NULL, 0, PipeCreator::PipeThread, NULL, 0, NULL );
}

DWORD PipeCreator::PipeThread(void *pContext)

{
    BOOL   fConnected = FALSE;
    DWORD  dwThreadId = 0;
    HANDLE hPipe = INVALID_HANDLE_VALUE, hThread = NULL;
    LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\InterfacePipe");

    // The main loop creates an instance of the named pipe and
    // then waits for a client to connect to it. When the client
    // connects, a thread is created to handle communications
    // with that client, and this loop is free to wait for the
    // next client connect request. It is an infinite loop.

    SECURITY_ATTRIBUTES sa;
    sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)malloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
    if (!InitializeSecurityDescriptor(sa.lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION))
    {
        DWORD er = ::GetLastError();
    }
    if (!SetSecurityDescriptorDacl(sa.lpSecurityDescriptor, TRUE, (PACL)0, FALSE))
    {
        DWORD er = ::GetLastError();
    }
    sa.nLength = sizeof sa;
    sa.bInheritHandle = TRUE;

    for (;;)
    {
hPipe = CreateNamedPipe(
            lpszPipename,             // pipe name
            PIPE_ACCESS_DUPLEX,       // read/write access
            PIPE_TYPE_MESSAGE |       // message type pipe
            PIPE_READMODE_MESSAGE |   // message-read mode
            PIPE_WAIT,                // blocking mode
            PIPE_UNLIMITED_INSTANCES, // max. instances
            BUFFER_SIZE,                  // output buffer size
            BUFFER_SIZE,                  // input buffer size
            0,                        // client time-out
            &sa);                    // default security attribute

        if (hPipe == INVALID_HANDLE_VALUE)
        {
            return -1;
        }

        // Wait for the client to connect; if it succeeds,
        // the function returns a nonzero value. If the function
        // returns zero, GetLastError returns ERROR_PIPE_CONNECTED.

        fConnected = ConnectNamedPipe(hPipe, NULL) ?
TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);

        if (fConnected)
        {

            this->instance =new InstanceCreator();
            connect(this->instance,SIGNAL(NewDataAvailable(MyData)),this,SLOT(NewDataAvailableForGUI(MyData)));
                      // Create a thread for this client.
            hThread = CreateThread(
                NULL,              // no security attribute
                0,                 // default stack size
                this->instance->InstanceThread,    // thread proc
                (LPVOID) hPipe,    // thread parameter
                0,                 // not suspended
                &dwThreadId);      // returns thread ID

            if (hThread == NULL)
            {
                return -1;
            }
            else
            {
                //Here I should recieve the emmited signal
                emit NewDataAvailableForGUI(this->newData);
                CloseHandle(hThread);
            }
        }
        else
            // The client could not connect, so close the pipe.
            CloseHandle(hPipe);
    }

    return ERROR_SUCCESS;
}

// This routine is a thread processing function to read from and reply to a client
// via the open pipe connection passed from the main loop. Note this allows
// the main loop to continue executing, potentially creating more threads of
// of this procedure to run concurrently, depending on the number of incoming
// client connections.
DWORD InstanceCreator::InstanceThread(LPVOID lpvParam)

{



HANDLE hHeap      = GetProcessHeap();
TCHAR* pchRequest = (TCHAR*)HeapAlloc(hHeap, 0, BUFFER_SIZE*sizeof(TCHAR));
TCHAR* pchReply   = (TCHAR*)HeapAlloc(hHeap, 0, BUFFER_SIZE*sizeof(TCHAR));

DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0;
BOOL fSuccess = FALSE;
HANDLE hPipe  = NULL;

// Do some extra error checking since the app will keep running even if this
// thread fails.z

//PostMessage((HWND)CMFCApplication1Dlg->textBox3->Handle.ToPointer(), WM_SETTEXT, 0, (LPARAM)L"TestDLL Try");

if (lpvParam == NULL)
{

    if (pchReply != NULL) HeapFree(hHeap, 0, pchReply);
    if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest);
    return (DWORD)-1;
}

if (pchRequest == NULL)
{

 if (pchReply != NULL) HeapFree(hHeap, 0, pchReply);
    return (DWORD)-1;
}

if (pchReply == NULL)
{

if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest);
    return (DWORD)-1;
}

// Print verbose messages. In production code, this should be for debugging only.
// The thread's parameter is a handle to a pipe object instance.

hPipe = (HANDLE) lpvParam;

// Loop until done reading
while (1)
{
    // Read client requests from the pipe. This simplistic code only allows messages
    // up to BUFSIZE characters in length.
    fSuccess = ReadFile(
        hPipe,        // handle to pipe
        pchRequest,    // buffer to receive data
        BUFFER_SIZE*sizeof(TCHAR), // size of buffer
        &cbBytesRead, // number of bytes read
        NULL);        // not overlapped I/O

    if (!fSuccess || cbBytesRead == 0)
    {

break;
    }

    MyData data;
    data.data=QString::fromStdWString(pchRequest);

    emit NewDataAvailable(data);

    // Process the incoming message.
    //GetAnswerToRequest(pchRequest, pchReply, &cbReplyBytes);

    if (wcscmp(pchRequest,L"msg1")==0)
        StringCchCopy( pchReply, BUFFER_SIZE, TEXT("Hi"));
    else
        StringCchCopy( pchReply, BUFFER_SIZE, TEXT("default echo answer"));

    cbReplyBytes = (lstrlen(pchReply)+1)*sizeof(TCHAR);
    // Write the reply to the pipe.
    fSuccess = WriteFile(
        hPipe,        // handle to pipe
        pchReply,     // buffer to write from
        cbReplyBytes, // number of bytes to write
        &cbWritten,   // number of bytes written
        NULL);        // not overlapped I/O

    if (!fSuccess || cbReplyBytes != cbWritten)
    {
        break;
    }
}

// Flush the pipe to allow the client to read the pipe's contents
// before disconnecting. Then disconnect the pipe, and close the
// handle to this pipe instance.

FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);

HeapFree(hHeap, 0, pchRequest);
HeapFree(hHeap, 0, pchReply);

return 1;
}

0 个答案:

没有答案