我正在尝试创建一个处理程序类来处理 C++ 中的管道。首先我可能会说我已经习惯了 C#,但对 C++ 和指针的概念还很陌生。
类中唯一的字段是一个变量,类型为 HANDLE (void *),
pipeHandle
,它存储 CreateFile()
返回的值。
我有一个方法,
ConnectPipe()
,它使用CreateFile()
来获取管道的句柄,以及一些错误检查。它将句柄存储在pipeHandle
中,然后完成执行。这似乎是有问题的,因为经过研究和调试,我发现 pipeHandle
的值在 ConnectPipe()
执行完成后发生了变化。我认为这是由于指针引用了 ConnectPipe()
中实例化的内容,然后在 ConnectPipe()
完成后被删除。
代码:
PipeManager.h:
#ifndef PIPE_MANAGER_H
#define PIPE_MANAGER_H
#include <Windows.h>
#include <string>
class PipeManager
{
private:
HANDLE pipeHandle;
void PipeConnect(LPCWSTR pipeFullName);
void PipeReceive(BYTE* outBuffer);
public:
PipeManager(std::string pipeName);
void Testing();
};
#endif
管道管理器.cpp:
#include "PipeManager.h"
#include <iostream>
void PipeManager::PipeConnect(LPCWSTR pipeFullName)
{
const int ATTEMPT_LIMIT = 10;
int attempts = 0;
do {
if (attempts > ATTEMPT_LIMIT) {
break;
}
pipeHandle = CreateFile(pipeFullName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (pipeHandle == INVALID_HANDLE_VALUE) {
std::cerr << "Failed to connect to the named pipe, error code " << GetLastError() << ". Trying again." << std::endl;
attempts++;
}
} while (pipeHandle == INVALID_HANDLE_VALUE);
}
void PipeManager::PipeReceive(BYTE* outBuffer)
{
DWORD read = 0; // Number of bytes read in each ReadFile() call
int index = 0;
do {
if (!ReadFile(pipeHandle, outBuffer + index, 1, &read, NULL)) {
std::cerr << "Failed to read from the named pipe, error code " << GetLastError() << std::endl;
break;
}
} while (outBuffer[index - 1] != 0); // Stop if the most recent byte was null-termination.
}
// Constructor for a named pipe, yet to be connected to
PipeManager::PipeManager(std::string pipeName) {
std::string fullName = "\\\\.\\pipe\\" + pipeName;
PipeConnect(std::wstring(fullName.begin(), fullName.end()).c_str());
}
void PipeManager::Testing()
{
BYTE buffer[1024];
PipeReceive(buffer);
}
CPPClient.cpp(应用程序入口点):
int main()
{
//return HandlePipe("TestingPipe", false);
PipeManager pipeManager = new PipeManager(std::string("TestingPipe"));
pipeManager.Testing();
}
我有一个正在运行的管道服务器(用 C# 编写),它创建“TestingPipe”,我知道它可以工作并且已经过测试。我还设法让管道客户端(用 C++ 编写)工作,但不在类内 - 只是一堆函数调用和
main()
方法中的内容。
当我运行上面的程序时,C# 服务器最初接受连接,但当客户端尝试读取“管道已损坏”时失败,而 C++ 客户端在尝试从管道读取时失败,并显示代码 6 无效句柄。
如何在对象的整个生命周期中保持
pipeHandle
不变,或者至少在 ConnectPipe
完成初始化后停止更改?
除非这是不可能的,在这种情况下,我每次想读取或写入管道时都必须重新连接到管道。
编辑: 删除不相关的代码
非常感谢 Igor Tandetnik - 在我的
main()
函数中,我使用了 new
关键字,它创建一个对象并将其复制到一个新对象中。正是这个导致了 pipeHandle
的改变,而不是我最初认为的引用问题。