Godot 4 源码分析 - 增加管道通信

学习研究Godot 4,很爽,虽然很庞杂,但相对于自己的水平来说,很强大,尤其是vulkan这块直接打包可用,省得自己从头琢磨。

一点一点地消化、优化与完善,最终才能成为自己的。

这段时间就在Godot的基础上,增加管道通信,实现Godot与本机已有程序进行通信,以备后续的无缝集成整合。

其实,Godot支持各种网络通信,支持UDP、TCP等。为什么非要实现管道通信,本质上还是想看看改造效果。最终目标是实现Godot软件与自己的DrGraph软件的管道通信

DrGraph端处理

为实现管道通信,根据Windows命名管道通信原理进行相应模块化实现。

class TDllData {void __fastcall CheckType(unsigned char destType);
public:__fastcall TDllData(unsigned char t = DRGRAPH_DLL_TYPE_NULL);__fastcall TDllData(const TDllData& copy);__fastcall ~TDllData();bool __fastcall IsEof() { return type == DRGRAPH_DLL_TYPE_NULL; };UnicodeString __fastcall GetHint();unsigned char type;union {bool 			value_bool;char 			value_char;unsigned char 	value_uchar;wchar_t 		value_wchar;short 			value_short;unsigned short 	value_ushort;int 			value_int;unsigned int 	value_uint;long 			value_long;unsigned long 	value_ulong;double 			value_double;long long		value_longlong;unsigned long long 	value_ulonglong;} value ;UnicodeString value_string;TDllData * __fastcall operator = (const TDllData & equal);operator bool();operator char();operator unsigned char();operator wchar_t();operator short();operator unsigned short();operator int();operator unsigned int();operator long();operator unsigned long();operator double();operator long long();operator unsigned long long();operator UnicodeString();
};class TDllStream : public CbwStream {typedef CbwStream inherited;TMemoryStream * FMemoryStream;DRGRAPH_PROPERTY(bool, Finished);DRGRAPH_PROPERTY(bool, WCharFlag);DRGRAPH_PROPERTY(int, WCharSize);
public:__fastcall TDllStream();__fastcall TDllStream(BYTE * datas, int len);__fastcall TDllStream(wchar_t * datas, int len);__fastcall ~TDllStream();void __fastcall Finish();TDllData __fastcall Next();void __fastcall Reset();UnicodeString __fastcall GetHint(UnicodeString desc = L"");int __fastcall NextFunType();__fastcall operator BYTE *();__fastcall operator wchar_t *();virtual bool __fastcall writeBytes(const void * p, int len) {CbwStream::writeBytes(p, len);FFinished = false;}//#ifdef DRGRAPH_USE_OPENCV
//			friend TDllStream & operator << (TDllStream & cofs, cv::Mat& mat);
//			friend TDllStream & operator >> (TDllStream & cifs, cv::Mat& mat);
//#endiffriend TDllStream & operator << (TDllStream & cofs, NStreamIOControl ctrl) {if(ctrl == ioReset)cofs.Reset();if(ctrl == ioRewind)cofs.Rewind();if(ctrl == ioFinish)cofs.Finish();return cofs;}friend TDllStream & operator << (TDllStream & cofs, bool value) {DLL_WRITE(DRGRAPH_DLL_TYPE_BOOL);if(cbw_debug_flag)THelper::Logi(L"写入[%s]类型 > %s", DllType2String(dlltype), TTypeConvert::Bool2String(value));unsigned char b = value ? 1 : 0;cofs.writeBytes(&b, sizeof(unsigned char));return cofs;}friend TDllStream & operator << (TDllStream & cofs, char value) {DLL_WRITE(DRGRAPH_DLL_TYPE_CHAR);if(cbw_debug_flag)THelper::Logi(L"写入[%s]类型 > %d[0X%02X, %c]", DllType2String(dlltype), int(value), value, value);cofs.writeBytes(&value, sizeof(char));return cofs;}friend TDllStream & operator << (TDllStream & cofs, unsigned char value) {DLL_WRITE(DRGRAPH_DLL_TYPE_UCHAR);if(cbw_debug_flag)THelper::Logi(L"写入[%s]类型 > %d[0X%02X, %c]", DllType2String(dlltype), int(value), value, value);cofs.writeBytes(&value, sizeof(unsigned char));return cofs;}friend TDllStream & operator << (TDllStream & cofs, wchar_t value) {DLL_WRITE(DRGRAPH_DLL_TYPE_WCHAR);if(cbw_debug_flag)THelper::Logi(L"写入[%s]类型 > %s", DllType2String(dlltype), UnicodeString(value));cofs.writeBytes(&value, sizeof(wchar_t));return cofs;}friend TDllStream & operator << (TDllStream & cofs, short value) {DLL_WRITE(DRGRAPH_DLL_TYPE_SHORT);if(cbw_debug_flag)THelper::Logi(L"写入[%s]类型 > %d", DllType2String(dlltype), int(value));cofs.writeBytes(&value, sizeof(short));return cofs;}friend TDllStream & operator << (TDllStream & cofs, unsigned short value) {DLL_WRITE(DRGRAPH_DLL_TYPE_USHORT);if(cbw_debug_flag)THelper::Logi(L"写入[%s]类型 > %d", DllType2String(dlltype), int(value));cofs.writeBytes(&value, sizeof(unsigned short));return cofs;}friend TDllStream & operator << (TDllStream & cofs, int value) {DLL_WRITE(DRGRAPH_DLL_TYPE_INT);if(cbw_debug_flag)THelper::Logi(L"写入[%s]类型 > %d", DllType2String(dlltype), int(value));cofs.writeBytes(&value, sizeof(int));return cofs;}friend TDllStream & operator << (TDllStream & cofs, unsigned int value) {DLL_WRITE(DRGRAPH_DLL_TYPE_UINT);if(cbw_debug_flag)THelper::Logi(L"写入[%s]类型 > %d", DllType2String(dlltype), int(value));cofs.writeBytes(&value, sizeof(unsigned int));return cofs;}friend TDllStream & operator << (TDllStream & cofs, long value) {DLL_WRITE(DRGRAPH_DLL_TYPE_LONG);if(cbw_debug_flag)THelper::Logi(L"写入[%s]类型 > %ld", DllType2String(dlltype), value);cofs.writeBytes(&value, sizeof(long));return cofs;}friend TDllStream & operator << (TDllStream & cofs, unsigned long value) {DLL_WRITE(DRGRAPH_DLL_TYPE_ULONG);if(cbw_debug_flag)THelper::Logi(L"写入[%s]类型 > %lu", DllType2String(dlltype), value);cofs.writeBytes(&value, sizeof(unsigned long));return cofs;}friend TDllStream & operator << (TDllStream & cofs, long long value) {DLL_WRITE(DRGRAPH_DLL_TYPE_LONGLONG);if(cbw_debug_flag)THelper::Logi(L"写入[%s]类型 > %lld", DllType2String(dlltype), value);cofs.writeBytes(&value, sizeof(long long));return cofs;}
//friend TDllStream & operator << (TDllStream & cofs, unsigned long long value) {DLL_WRITE(DRGRAPH_DLL_TYPE_ULONGLONG);if(cbw_debug_flag)THelper::Logi(L"写入[%s]类型 > %llu", DllType2String(dlltype), value);cofs.writeBytes(&value, sizeof(unsigned long long));return cofs;}friend TDllStream & operator << (TDllStream & cofs, float value) {double d = value;cofs << d;return cofs;}friend TDllStream & operator << (TDllStream & cofs, double value) {DLL_WRITE(DRGRAPH_DLL_TYPE_DOUBLE);if(cbw_debug_flag)THelper::Logi(L"写入[%s]类型 > %s", DllType2String(dlltype), TTypeConvert::Double2String(value, 3));cofs.writeBytes(&value, sizeof(double));return cofs;}friend TDllStream & operator << (TDllStream & cofs, char*str) {UnicodeString string = str;cofs << string;return cofs;}friend TDllStream & operator << (TDllStream & cofs, wchar_t*str) {UnicodeString string = str;cofs << string;return cofs;}friend TDllStream & operator << (TDllStream & cofs, UnicodeString value) {DLL_WRITE(DRGRAPH_DLL_TYPE_STRING);if(cbw_debug_flag)THelper::Logi(L"写入[%s]类型 > %s", DllType2String(dlltype), value);int iTextLen = WideCharToMultiByte(CP_UTF8, 0, value.w_str(), -1, NULL, 0, NULL, NULL);char * chBuffer = new char[iTextLen + 1];WideCharToMultiByte(CP_UTF8, 0, value.w_str(), -1, chBuffer, iTextLen, NULL, NULL);cofs.writeBytes(&iTextLen, sizeof(int));cofs.writeBytes(chBuffer, iTextLen);delete[]chBuffer;return cofs;}friend TDllStream & operator >> (TDllStream & cifs, UnicodeString & q) {int length;cifs >> length;char * chBuffer = new char[length + 1];cifs.readBytes(chBuffer, length);chBuffer[length] = '\0';if(cifs.WCharFlag == false) {int wLength = length + 1;wchar_t *wcBuffer = new wchar_t[wLength];MultiByteToWideChar(CP_UTF8, 0, chBuffer, wLength, wcBuffer, wLength);wcBuffer[length] = L'\0';q = UnicodeString(wcBuffer);delete wcBuffer;} elseq = UnicodeString(chBuffer);delete chBuffer;return cifs;}friend TDllStream & operator << (TDllStream & cofs, Variant& data) {switch(data.Type()) {case varBoolean: 	cofs << bool(data);				break;case varEmpty:case varNull: 		cofs << 0;						break;case varSingle:     cofs << float(data);			break;case varDouble:     cofs << double(data);			break;case varString:case varUString:	cofs << (wchar_t *)(data);	break;case varSmallint:case varInteger:case varWord:  		cofs << int(data);				break;case varInt64:		cofs << __int64(data);			break;case varUInt64:		cofs << (unsigned __int64)(data);	break;case varByte:		cofs << (unsigned char)(data);	break;case 0x10:			cofs << short(data);			break;     		// varShortIntcase varLongWord:	cofs << long(data);				break;default:  			cofs << (wchar_t *)(data);	break;}return cofs;}friend TDllStream & operator << (TDllStream & cofs, TDllData & data) {if(data.type == DRGRAPH_DLL_TYPE_STRING)cofs << data.value_string;else if(data.type == DRGRAPH_DLL_TYPE_INT)cofs << data.value.value_int;else if(data.type == DRGRAPH_DLL_TYPE_DOUBLE)cofs << data.value.value_double;else if(data.type == DRGRAPH_DLL_TYPE_BOOL)cofs << data.value.value_bool;else if(data.type == DRGRAPH_DLL_TYPE_UCHAR)cofs << data.value.value_uchar;else if(data.type == DRGRAPH_DLL_TYPE_CHAR)cofs << data.value.value_char;else if(data.type == DRGRAPH_DLL_TYPE_WCHAR)cofs << data.value.value_wchar;else if(data.type == DRGRAPH_DLL_TYPE_SHORT)cofs << data.value.value_short;else if(data.type == DRGRAPH_DLL_TYPE_LONG)cofs << data.value.value_long;else if(data.type == DRGRAPH_DLL_TYPE_USHORT)cofs << data.value.value_ushort;else if(data.type == DRGRAPH_DLL_TYPE_UINT)cofs << data.value.value_uint;else if(data.type == DRGRAPH_DLL_TYPE_ULONG)cofs << data.value.value_ulong;else if(data.type == DRGRAPH_DLL_TYPE_LONGLONG)cofs << data.value.value_longlong;else if(data.type == DRGRAPH_DLL_TYPE_ULONGLONG)cofs << data.value.value_ulonglong;else if(data.type == DRGRAPH_DLL_TYPE_NULL)cofs.Finish();return cofs;}///**************************************************************friend TDllStream & operator >> (TDllStream & cifs, TDllData & data) {if(data.type == DRGRAPH_DLL_TYPE_STRING)cifs >> data.value_string;else if(data.type == DRGRAPH_DLL_TYPE_INT)cifs.readBytes(&data.value, sizeof(int));else if(data.type == DRGRAPH_DLL_TYPE_DOUBLE)cifs.readBytes(&data.value, sizeof(double));else if(data.type == DRGRAPH_DLL_TYPE_BOOL)cifs.readBytes(&data.value, sizeof(unsigned char));else if(data.type == DRGRAPH_DLL_TYPE_UCHAR)cifs.readBytes(&data.value, sizeof(unsigned char));else if(data.type == DRGRAPH_DLL_TYPE_CHAR)cifs.readBytes(&data.value, sizeof(char));else if(data.type == DRGRAPH_DLL_TYPE_WCHAR)cifs.readBytes(&data.value, sizeof(wchar_t));else if(data.type == DRGRAPH_DLL_TYPE_SHORT)cifs.readBytes(&data.value, sizeof(short));else if(data.type == DRGRAPH_DLL_TYPE_LONG)cifs.readBytes(&data.value, sizeof(long));else if(data.type == DRGRAPH_DLL_TYPE_USHORT)cifs.readBytes(&data.value, sizeof(unsigned short));else if(data.type == DRGRAPH_DLL_TYPE_UINT)cifs.readBytes(&data.value, sizeof(unsigned int));else if(data.type == DRGRAPH_DLL_TYPE_ULONG)cifs.readBytes(&data.value, sizeof(unsigned long));else if(data.type == DRGRAPH_DLL_TYPE_LONGLONG)cifs.readBytes(&data.value, sizeof(long long));else if(data.type == DRGRAPH_DLL_TYPE_ULONG)cifs.readBytes(&data.value, sizeof(unsigned long long));else if(data.type == DRGRAPH_DLL_TYPE_NULL)return cifs;return cifs;}friend TDllStream & operator << (TDllStream & cofs, TPoint point) {cofs << point.x;cofs << point.y;return cofs;}friend TDllStream & operator >> (TDllStream & cifs, TPoint& point) {cifs >> point.x;cifs >> point.y;return cifs;}friend TDllStream & operator << (TDllStream & cofs, TRect rect) {cofs << rect.left;cofs << rect.top;cofs << rect.right;cofs << rect.bottom;return cofs;}friend TDllStream & operator >> (TDllStream & cifs, TRect& rect) {cifs >> rect.left;cifs >> rect.top;cifs >> rect.right;cifs >> rect.bottom;return cifs;}
};#define PIPE_CONNECTING_STATE 0
#define PIPE_READING_STATE 1
#define PIPE_WRITING_STATE 2
#define PIPE_INSTANCES 4
#define PIPE_TIMEOUT 5000
#define PIPE_BUFSIZE 4096#define DRSTREAM_FUNCTION_NONE 0
#define DRSTREAM_FUNCTION_SET 1
#define DRSTREAM_FUNCTION_GET 2
#define DRSTREAM_FUNCTION_STATUS 3typedef struct {OVERLAPPED oOverlap;HANDLE hPipeInst;TCHAR wRequestBuffer[PIPE_BUFSIZE];DWORD cbRead;char wResponseBuffer[PIPE_BUFSIZE];DWORD cbWrite;DWORD dwState;BOOL fPendingIO;
} PIPEINST, *LPPIPEINST;class TPipeStream : public TDllStream {class TPipeThread : public TThread {friend class TPipeStream;PIPEINST Pipe[PIPE_INSTANCES];HANDLE hEvents[PIPE_INSTANCES];private:HANDLE hPipe;TPipeStream * FOwnerStream;void __fastcall Execute();public:__fastcall TPipeThread(TPipeStream * stream);__fastcall ~TPipeThread();void __fastcall DisconnectAndReconnect(DWORD);bool __fastcall ConnectToNewClient(HANDLE, LPOVERLAPPED);bool __fastcall GetAnswerToRequest(LPPIPEINST pipe, int index);};DRGRAPH_PROPERTY(TObjectByNameEvent, OnFindObject);
public:__fastcall TPipeStream(UnicodeString pipeName);__fastcall ~TPipeStream();void __fastcall ReportError(UnicodeString desc);void __fastcall WritePipe(TDllStream& os, int destPipeIndex = -1);TPipeThread * PipeThread;DRGRAPH_PROPERTY(UnicodeString, PipeName);DRGRAPH_PROPERTY(UnicodeString, Prefix);DRGRAPH_PROPERTY(int, LastPipeIndex);
};

源程序实现:


UnicodeString __fastcall TDllData::GetHint() {UnicodeString result = FORMAT(L"[%s]类型 > 值 = ", DllType2String(type));result +=type == DRGRAPH_DLL_TYPE_BOOL ? TTypeConvert::Bool2String(value.value_bool) :type == DRGRAPH_DLL_TYPE_CHAR ? FORMAT(L"%d[0X%02X, %c]", value.value_char, value.value_char, value.value_char) :type == DRGRAPH_DLL_TYPE_UCHAR ? FORMAT(L"%d[0X%02X, %c]", value.value_uchar, value.value_uchar, value.value_uchar) :type == DRGRAPH_DLL_TYPE_WCHAR ? FORMAT(L"%s", UnicodeString(value.value_wchar)) :type == DRGRAPH_DLL_TYPE_SHORT ? FORMAT(L"%d", value.value_short) :type == DRGRAPH_DLL_TYPE_USHORT ? FORMAT(L"%d", value.value_ushort) :type == DRGRAPH_DLL_TYPE_INT ? FORMAT(L"%d", value.value_int) :type == DRGRAPH_DLL_TYPE_UINT ? FORMAT(L"%d", value.value_uint) :type == DRGRAPH_DLL_TYPE_LONG ? FORMAT(L"%ld", value.value_long) :type == DRGRAPH_DLL_TYPE_ULONG ? FORMAT(L"%lu", value.value_ulong) :type == DRGRAPH_DLL_TYPE_LONGLONG ? FORMAT(L"%lld", value.value_longlong) :type == DRGRAPH_DLL_TYPE_ULONGLONG ? FORMAT(L"%llu", value.value_ulonglong) :type == DRGRAPH_DLL_TYPE_DOUBLE ? FORMAT(L"%s", TTypeConvert::Double2String(value.value_double, 3)) :type == DRGRAPH_DLL_TYPE_STRING ? FORMAT(L"%s", value_string) :UnicodeString(L"已结束");return result;
}void __fastcall TDllData::CheckType(unsigned char destType) {if(destType != type)THelper::Logw(L"类型不正确,转换可能会出现偏差,请检查协议 > 当前类型: %s, 目标类型: %s", DllType2String(type), DllType2String(destType));
}TDllData::operator bool() {CheckType(DRGRAPH_DLL_TYPE_BOOL);return value.value_bool;
}TDllData::operator char() {CheckType(DRGRAPH_DLL_TYPE_CHAR);return value.value_char;
}TDllData::operator unsigned char() {CheckType(DRGRAPH_DLL_TYPE_UCHAR);return value.value_uchar;
}TDllData::operator wchar_t() {CheckType(DRGRAPH_DLL_TYPE_WCHAR);return value.value_wchar;
}TDllData::operator short() {CheckType(DRGRAPH_DLL_TYPE_SHORT);return value.value_short;
}TDllData::operator unsigned short() {CheckType(DRGRAPH_DLL_TYPE_USHORT);return value.value_ushort;
}TDllData::operator int() {CheckType(DRGRAPH_DLL_TYPE_INT);return value.value_int;
}TDllData::operator unsigned int() {CheckType(DRGRAPH_DLL_TYPE_UINT);return value.value_uint;
}TDllData::operator long() {CheckType(DRGRAPH_DLL_TYPE_LONG);return value.value_long;
}TDllData::operator unsigned long() {CheckType(DRGRAPH_DLL_TYPE_ULONG);return value.value_ulong;
}TDllData::operator long long() {CheckType(DRGRAPH_DLL_TYPE_LONGLONG);return value.value_longlong;
}TDllData::operator unsigned long long() {CheckType(DRGRAPH_DLL_TYPE_ULONGLONG);return value.value_ulonglong;
}TDllData::operator double() {CheckType(DRGRAPH_DLL_TYPE_DOUBLE);return value.value_double;
}TDllData::operator UnicodeString() {CheckType(DRGRAPH_DLL_TYPE_STRING);return value_string;
}__fastcall TDllStream::TDllStream() : CbwStream() {FMemoryStream = new TMemoryStream;Stream = FMemoryStream;FFinished = false;WCharFlag = false;
}__fastcall TDllStream::TDllStream(BYTE * datas, int len) : CbwStream() {FMemoryStream = new TMemoryStream;FMemoryStream->Write(datas, len);FMemoryStream->Position = 0;Stream = FMemoryStream;FFinished = false;WCharFlag = false;
}__fastcall TDllStream::TDllStream(wchar_t * datas, int len) {FMemoryStream = new TMemoryStream;FMemoryStream->Write(datas, len);FMemoryStream->Position = 0;Stream = FMemoryStream;FFinished = false;WCharFlag = true;
}__fastcall TDllStream::~TDllStream() {
}void __fastcall TDllStream::Finish() {if(cbw_debug_flag)THelper::Logi(L"结束...");if(FFinished)return;unsigned short value = DRGRAPH_DLL_TYPE_NULL;writeBytes(&value, sizeof(unsigned short));FFinished = true;
}TDllData __fastcall TDllStream::Next() {unsigned char type;bool readed = readBytes(&type, sizeof(unsigned char));TDllData result(type);if(readed)(*this) >> result;return result;
}int __fastcall TDllStream::NextFunType() {if(Size - Position < (sizeof(int) - 1))return 0;GET_DLL_DATA(int, funType, this);if(READING_DLL_DATA.type == DRGRAPH_DLL_TYPE_NULL)funType = DRSTREAM_FUNCTION_NONE;return funType;
}__fastcall TDllStream::operator BYTE *() {FMemoryStream->Position = 0;int len = Stream->Size;BYTE * result = new BYTE[len];FMemoryStream->Read(result, len);FMemoryStream->Position = 0;return result;
}__fastcall TDllStream::operator wchar_t *() {FMemoryStream->Position = 0;int len = Stream->Size;BYTE * result = new BYTE[len];FMemoryStream->Read(result, len);FMemoryStream->Position = 0;WCharSize = MultiByteToWideChar(CP_ACP, 0, result, -1, NULL, 0);wchar_t * ws = new wchar_t[WCharSize];MultiByteToWideChar(CP_ACP, 0, result, -1, ws, WCharSize);delete[] result;return ws;
}void __fastcall TDllStream::Reset() {CBW_DELETE(FMemoryStream);FMemoryStream = new TMemoryStream;Stream = FMemoryStream;
}UnicodeString __fastcall TDllStream::GetHint(UnicodeString desc) {UnicodeString result = FORMAT(L"%s中内容:", desc.Length() > 0 ? desc.w_str() : L"DllStream流");do {if(EOF_Flag)break;TDllData data = Next();if(data.IsEof())break;result += FORMAT(L"\n\t%s", data.GetHint());} while(true);return result;
}__fastcall TDllData::TDllData(unsigned char t) {type = t;
}__fastcall TDllData::TDllData(const TDllData& copy) {type = copy.type;value = copy.value;value_string = copy.value_string;
}TDllData * __fastcall TDllData::operator = (const TDllData & equal) {type = equal.type;value = equal.value;value_string = equal.value_string;return this;
}__fastcall TDllData::~TDllData() {
}__fastcall TPipeStream::TPipeStream(UnicodeString pipeName) {FPipeName = pipeName;FPrefix = FORMAT(L"管道服务 %s", PipeName);OnFindObject = NULL;PipeThread = new TPipeThread(this);THelper::Logi(L"创建 %s", FPrefix);
}__fastcall TPipeStream::~TPipeStream() {
}void __fastcall TPipeStream::ReportError(UnicodeString desc) {UnicodeString info = FORMAT(L"【%s.错误】 > %s", FPrefix, desc);THelper::Loge(THelper::Util::GetSystemErrorInfo(false, info));
}__fastcall TPipeStream::TPipeThread::TPipeThread(TPipeStream * stream) : TThread(true) {FreeOnTerminate = true;FOwnerStream = stream;for (int i = 0; i < PIPE_INSTANCES; i++)hEvents[i] = NULL;Suspended = false;
}__fastcall TPipeStream::TPipeThread::~TPipeThread() {if(FOwnerStream->PipeThread == this)FOwnerStream->PipeThread = NULL;
}void __fastcall TPipeStream::TPipeThread::DisconnectAndReconnect(DWORD i)
{if (!DisconnectNamedPipe(Pipe[i].hPipeInst))FOwnerStream->ReportError("DisconnectNamedPipe 失败");Pipe[i].fPendingIO = ConnectToNewClient(Pipe[i].hPipeInst,&Pipe[i].oOverlap);Pipe[i].dwState = Pipe[i].fPendingIO ?PIPE_CONNECTING_STATE : // still connectingPIPE_READING_STATE;     // ready to read
}// ConnectToNewClient(HANDLE, LPOVERLAPPED)
// This function is called to start an overlapped connect operation.
// It returns TRUE if an operation is pending or FALSE if the
// connection has been completed.bool __fastcall TPipeStream::TPipeThread::ConnectToNewClient(HANDLE hPipe, LPOVERLAPPED lpo)
{bool fConnected, fPendingIO = false;fConnected = ConnectNamedPipe(hPipe, lpo);if (fConnected){FOwnerStream->ReportError(L"调用ConnectToNewClient时,ConnectNamedPipe 失败 > fConnected == false");return 0;}switch (GetLastError()) {case ERROR_IO_PENDING:	// The overlapped connection in progress.fPendingIO = TRUE;break;case ERROR_PIPE_CONNECTED:// Client is already connected, so signal an event.if (SetEvent(lpo->hEvent))break;default:    				// If an error occurs during the connect operation...FOwnerStream->ReportError("调用ConnectToNewClient时,ConnectNamedPipe 失败 > GetLastError == default");return 0;}return fPendingIO;
}void __fastcall TPipeStream::TPipeThread::Execute() {DWORD i, dwWait, cbRet, dwErr;BOOL fSuccess;THelper::Windows::DebugCurrentThread(ndttAdd, FORMAT(L"【%s】", FOwnerStream->Prefix));LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\drgraph");// 创建多个命名管道for (i = 0; i < PIPE_INSTANCES; i++) {hEvents[i] = CreateEvent(NULL,    // default security attributeTRUE,    // manual-reset eventTRUE,    // initial state = signaledNULL);   // unnamed event objectif (hEvents[i] == NULL) {FOwnerStream->ReportError("CreateEvent failed");return;}Pipe[i].oOverlap.hEvent = hEvents[i];Pipe[i].hPipeInst = CreateNamedPipe(lpszPipename,            	// pipe namePIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,    	// overlapped modePIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,PIPE_INSTANCES,          	// number of instancesPIPE_BUFSIZE*sizeof(TCHAR),	// output buffer sizePIPE_BUFSIZE*sizeof(TCHAR),	// input buffer sizePIPE_TIMEOUT,            	// client time-outNULL);                   	// default security attributesif (Pipe[i].hPipeInst == INVALID_HANDLE_VALUE) {FOwnerStream->ReportError("CreateNamedPipe failed");Pipe[i].hPipeInst = NULL;return;}Pipe[i].fPendingIO = ConnectToNewClient(Pipe[i].hPipeInst, &Pipe[i].oOverlap);Pipe[i].dwState = Pipe[i].fPendingIO ?PIPE_CONNECTING_STATE : // still connectingPIPE_READING_STATE;     // ready to read}// 监听各管道while (!Terminated) {dwWait = WaitForMultipleObjects(PIPE_INSTANCES,    	// number of event objectshEvents,      		// array of event objectsFALSE,        		// does not wait for all50);if( WAIT_TIMEOUT == dwWait)continue;i = dwWait - WAIT_OBJECT_0;  // determines which pipeif (i < 0 || i > (PIPE_INSTANCES - 1)) {FOwnerStream->ReportError(FORMAT("WaitForMultipleObjects 监听结果下标[%d]越界: 有效范围区间 (0 ~ %d)", i, PIPE_INSTANCES - 1));break;}if (Pipe[i].fPendingIO) {	// Get the result if the operation was pending.fSuccess = GetOverlappedResult(Pipe[i].hPipeInst, // handle to pipe&Pipe[i].oOverlap, // OVERLAPPED structure&cbRet,            // bytes transferredFALSE);            // do not waitswitch (Pipe[i].dwState) { 	// Pending connect operationcase PIPE_CONNECTING_STATE:if (! fSuccess) {FOwnerStream->ReportError(FORMAT("调用GetOverlappedResult后,Pipe[%d].dwState 值为 PIPE_CONNECTING_STATE > 不再监听,退出监听线程", i));return;}Pipe[i].dwState = PIPE_READING_STATE;break;case PIPE_READING_STATE:	// Pending read operationif (! fSuccess || cbRet == 0) {DisconnectAndReconnect(i);continue;}Pipe[i].cbRead = cbRet;Pipe[i].dwState = PIPE_WRITING_STATE;break;case PIPE_WRITING_STATE:	// Pending write operationif (! fSuccess || cbRet != Pipe[i].cbWrite) {DisconnectAndReconnect(i);continue;}Pipe[i].dwState = PIPE_READING_STATE;break;default:FOwnerStream->ReportError(FORMAT("调用GetOverlappedResult后,Pipe[%d].dwState 值为未处理值[%d] > 不再监听,退出监听线程", Pipe[i].dwState));return;}}switch (Pipe[i].dwState) {	// The pipe state determines which operation to do next.case PIPE_READING_STATE:  	// The pipe instance is connected to the clientfSuccess = ReadFile(  	// and is ready to read a request from the client.Pipe[i].hPipeInst,Pipe[i].wRequestBuffer,PIPE_BUFSIZE*sizeof(TCHAR),&Pipe[i].cbRead,&Pipe[i].oOverlap);if (fSuccess && Pipe[i].cbRead != 0) {	// The read operation completed successfully.Pipe[i].fPendingIO = FALSE;Pipe[i].dwState = PIPE_WRITING_STATE;continue;}// The read operation is still pending.dwErr = GetLastError();if (! fSuccess && (dwErr == ERROR_IO_PENDING)) {Pipe[i].fPendingIO = TRUE;continue;}DisconnectAndReconnect(i);	// An error occurred; disconnect from the client.break;case PIPE_WRITING_STATE:  			// The request was successfully read from the client.GetAnswerToRequest(&Pipe[i], i);  	// Get the reply data and write it to the client.fSuccess = true;fSuccess = WriteFile(           // true: 有返回数据内容Pipe[i].hPipeInst,Pipe[i].wResponseBuffer,Pipe[i].cbWrite,&cbRet,&Pipe[i].oOverlap);if (fSuccess && cbRet == Pipe[i].cbWrite) {	// The write operation completed successfully.Pipe[i].fPendingIO = FALSE;Pipe[i].dwState = PIPE_READING_STATE;continue;}// The write operation is still pending.dwErr = GetLastError();if (! fSuccess && (dwErr == ERROR_IO_PENDING)) {Pipe[i].fPendingIO = TRUE;continue;}DisconnectAndReconnect(i);	// An error occurred; disconnect from the client.break;default:FOwnerStream->ReportError("Invalid pipe state.");return;}}THelper::Windows::DebugCurrentThread(ndttRemove);
}bool __fastcall TPipeStream::TPipeThread::GetAnswerToRequest(LPPIPEINST pipe, int index)
{FOwnerStream->LastPipeIndex = index;TDllStream is(pipe->wRequestBuffer, pipe->cbRead);THelper::Logi(L"接收到pipe[%d]信息 > %s", index, is.GetHint());THelper::Debug::DoLogOutput();TDllStream os;OnRequest_Stream(&is, &os, FOwnerStream->OnFindObject);if(os.Size == 0)os << DRSTREAM_FUNCTION_NONE;// << "ERROR" << "No Response";if(os.Size > 0) {os << ioFinish;os.Rewind();BYTE * data = (BYTE *)os;pipe->cbWrite = os.Size;memcpy(pipe->wResponseBuffer, data, os.Size);THelper::Logi(L"发送 %d 字节 > %s", pipe->cbWrite, os.GetHint());delete data;return true;	// 有返回内容} return false;
}void __fastcall TPipeStream::WritePipe(TDllStream& os, int destPipeIndex) {if(destPipeIndex == -1) {destPipeIndex = LastPipeIndex;if(destPipeIndex == -1)destPipeIndex = 0;}if(os.Size == 0)os << DRSTREAM_FUNCTION_NONE;if(os.Size > 0) {os << ioFinish;os.Rewind();BYTE * data = (BYTE *)os;UnicodeString hint = THelper::Debug::GetHint(data, os.Size);THelper::Logi(L"[Pipe.发送] > %s", hint);LPPIPEINST pipe = &(PipeThread->Pipe[destPipeIndex]);pipe->cbWrite = os.Size;memcpy(pipe->wResponseBuffer, data, os.Size);DWORD i, dwWait, cbRet, dwErr;bool fSuccess = WriteFile(           // true: 有返回数据内容pipe->hPipeInst,data,os.Size,&cbRet,NULL);if (fSuccess && cbRet == os.Size) {	// The write operation completed successfully.THelper::Logi(L"成功发送 %d 字节 > %s", os.Size, os.GetHint());return;}THelper::Loge(L"失败发送 %d 字节 > %s", os.Size, os.GetHint());delete data;}
}

在调用时,简单声明即可访问其属性与方法。

void __fastcall TMainForm::Button_DebugTestClick(TObject *Sender)
{if(PipeStreamServer == NULL) {CBW_DELETE(PipeStreamServer);PipeStreamServer = new TPipeStream(L"drgraph");PipeStreamServer->OnFindObject = FindObjectByName;//FCurrentForm->FindMetaByName;} else {TDllStream dsStatus;dsStatus << DRSTREAM_FUNCTION_STATUS << L"OK" << L"drgraph.姓名 = ArWen";PipeStreamServer->WritePipe(dsStatus);}
}

Godot端处理

直接在源码中增加CbwPipe.cpp与CbwPipe.h,基于使用方法习惯,相应编写实现

#pragma once#include "core/os/os.h"
#include <stdarg.h>
#include <stdlib.h>std::string String2std(String str);
wchar_t *char32ToWchar(const char32_t *char32Str);
typedef unsigned char BYTE;
#define __property(type, var, read, write) __declspec(property(read, write)) type var#define DRSTREAM_FUNCTION_NONE 0
#define DRSTREAM_FUNCTION_SET 1
#define DRSTREAM_FUNCTION_GET 2
#define DRSTREAM_FUNCTION_STATUS 3enum SEEK_ORIGIN {SO_BEGINNING = 0,SO_CURRENT = 1,SO_END = 2
};enum NStreamIOControl {ioReset,ioRewind,ioFinish
};extern bool cbw_debug_flag;
#define DRGRAPH_DLL_TYPE_NULL 0
#define DRGRAPH_DLL_TYPE_BOOL 1
#define DRGRAPH_DLL_TYPE_CHAR 2
#define DRGRAPH_DLL_TYPE_UCHAR 3
#define DRGRAPH_DLL_TYPE_WCHAR 4
#define DRGRAPH_DLL_TYPE_SHORT 5
#define DRGRAPH_DLL_TYPE_USHORT 6
#define DRGRAPH_DLL_TYPE_INT 7
#define DRGRAPH_DLL_TYPE_UINT 8
#define DRGRAPH_DLL_TYPE_LONG 9
#define DRGRAPH_DLL_TYPE_ULONG 10
#define DRGRAPH_DLL_TYPE_DOUBLE 11
#define DRGRAPH_DLL_TYPE_STRING 12
#define DRGRAPH_DLL_TYPE_LONGLONG 13
#define DRGRAPH_DLL_TYPE_ULONGLONG 14#define DLL_WRITE(t)                                   \unsigned char dlltype = t;                         \cofs.WriteBuffer(&dlltype, sizeof(unsigned char)); \cofs.Finished = false;std::string DllType2String(unsigned char type);
std::string Double2String(double value, int maxBits = 8, int fixedFlag = false, int width = 0);
std::string WChar2String(wchar_t *pwszSrc);
std::string WChar2String(const wchar_t *pwszSrc);class TDllData {void CheckType(unsigned char destType);public:TDllData(unsigned char t = DRGRAPH_DLL_TYPE_NULL);TDllData(const TDllData &copy);~TDllData();bool IsEof() { return type == DRGRAPH_DLL_TYPE_NULL; };std::string GetHint();unsigned char type;union {bool value_bool;char value_char;unsigned char value_uchar;wchar_t value_wchar;short value_short;unsigned short value_ushort;int value_int;unsigned int value_uint;long value_long;unsigned long value_ulong;double value_double;long long value_longlong;unsigned long long value_ulonglong;} value;std::string value_string;TDllData *operator=(const TDllData &equal);operator bool();operator char();operator unsigned char();operator wchar_t();operator short();operator unsigned short();operator int();operator unsigned int();operator long();operator unsigned long();operator double();operator long long();operator unsigned long long();operator std::string();
};class TDllStream {
public:enum { DEFAULT_MEMORY_DELTA = 1024 }; // 默认内存步长enum { MIN_MEMORY_DELTA = 256 }; // 最小内存步长private:char *m_pMemory; // 缓冲区指针int m_nSize; // 当前流的大小int m_nPosition; // 当前位置int m_nCapacity; // 缓冲区大小.真正大大小.包含给未来分配的长度int m_nMemoryDelta; // 增长的步长bool Finished;public:void SetPointer(void *pMemory, int nSize);void SetMemoryDelta(int nNewMemoryDelta);void SetCapacity(int nNewCapacity);char *Realloc(int &nNewCapacity);int GetSize() const;void SetSize(int nSize);int GetPosition() const;void SetPosition(int nPos);int Read(void *pBuffer, int nCount);int Write(const void *pBuffer, int nCount);int Seek(int nOffset, SEEK_ORIGIN nSeekOrigin);public:explicit TDllStream(int nMemoryDelta = DEFAULT_MEMORY_DELTA) :m_nCapacity(0), m_pMemory(NULL), m_nSize(0), m_nPosition(0) {SetMemoryDelta(nMemoryDelta);Finished = false;}TDllStream(BYTE *datas, int len);~TDllStream();public:char *GetMemory() { return m_pMemory; }void *GetCurrentPtr() { return m_pMemory + m_nPosition; }bool ReadBuffer(void *pBuffer, int nCount);bool WriteBuffer(void *pBuffer, int nCount);void Clear();bool IsEOF();void Rewind();void Finish();TDllData Next();void Reset();int NextFunType();operator BYTE *();__property(int, Size, get = GetSize, put = SetSize);__property(int, Position, get = GetPosition, put = SetPosition);public:friend TDllStream &operator<<(TDllStream &cofs, NStreamIOControl ctrl) {if (ctrl == ioReset)cofs.Reset();if (ctrl == ioRewind)cofs.Rewind();if (ctrl == ioFinish)cofs.Finish();return cofs;}friend TDllStream &operator<<(TDllStream &cofs, bool value) {DLL_WRITE(DRGRAPH_DLL_TYPE_BOOL);if (cbw_debug_flag)OS::get_singleton()->print("[DllStream] > 写入[%s]类型 > %s\n", DllType2String(dlltype).c_str(), value ? "true" : "false");unsigned char b = value ? 1 : 0;cofs.WriteBuffer(&b, sizeof(unsigned char));return cofs;}friend TDllStream &operator<<(TDllStream &cofs, char value) {DLL_WRITE(DRGRAPH_DLL_TYPE_CHAR);if (cbw_debug_flag)OS::get_singleton()->print("[DllStream] > 写入[%s]类型 > %d[0X%02X, %c]\n", DllType2String(dlltype).c_str(), int(value), value, value);cofs.WriteBuffer(&value, sizeof(char));return cofs;}friend TDllStream &operator<<(TDllStream &cofs, unsigned char value) {DLL_WRITE(DRGRAPH_DLL_TYPE_UCHAR);if (cbw_debug_flag)OS::get_singleton()->print("[DllStream] > 写入[%s]类型 > %d[0X%02X, %c]\n", DllType2String(dlltype).c_str(), int(value), value, value);cofs.WriteBuffer(&value, sizeof(unsigned char));return cofs;}friend TDllStream &operator<<(TDllStream &cofs, wchar_t value) {DLL_WRITE(DRGRAPH_DLL_TYPE_WCHAR);if (cbw_debug_flag)OS::get_singleton()->print("[DllStream] > 写入[%s]类型 > %lc\n", DllType2String(dlltype).c_str(), value);cofs.WriteBuffer(&value, sizeof(wchar_t));return cofs;}friend TDllStream &operator<<(TDllStream &cofs, short value) {DLL_WRITE(DRGRAPH_DLL_TYPE_SHORT);if (cbw_debug_flag)OS::get_singleton()->print("[DllStream] > 写入[%s]类型 > %d\n", DllType2String(dlltype).c_str(), int(value));cofs.WriteBuffer(&value, sizeof(short));return cofs;}friend TDllStream &operator<<(TDllStream &cofs, unsigned short value) {DLL_WRITE(DRGRAPH_DLL_TYPE_USHORT);if (cbw_debug_flag)OS::get_singleton()->print("[DllStream] > 写入[%s]类型 > %d\n", DllType2String(dlltype).c_str(), int(value));cofs.WriteBuffer(&value, sizeof(unsigned short));return cofs;}friend TDllStream &operator<<(TDllStream &cofs, int value) {DLL_WRITE(DRGRAPH_DLL_TYPE_INT);if (cbw_debug_flag)OS::get_singleton()->print("[DllStream] > 写入[%s]类型 > %d\n", DllType2String(dlltype).c_str(), int(value));cofs.WriteBuffer(&value, sizeof(int));return cofs;}friend TDllStream &operator<<(TDllStream &cofs, unsigned int value) {DLL_WRITE(DRGRAPH_DLL_TYPE_UINT);if (cbw_debug_flag)OS::get_singleton()->print("[DllStream] > 写入[%s]类型 > %d\n", DllType2String(dlltype).c_str(), int(value));cofs.WriteBuffer(&value, sizeof(unsigned int));return cofs;}friend TDllStream &operator<<(TDllStream &cofs, long value) {DLL_WRITE(DRGRAPH_DLL_TYPE_LONG);if (cbw_debug_flag)OS::get_singleton()->print("[DllStream] > 写入[%s]类型 > %ld\n", DllType2String(dlltype).c_str(), value);cofs.WriteBuffer(&value, sizeof(long));return cofs;}friend TDllStream &operator<<(TDllStream &cofs, unsigned long value) {DLL_WRITE(DRGRAPH_DLL_TYPE_ULONG);if (cbw_debug_flag)OS::get_singleton()->print("[DllStream] > 写入[%s]类型 > %lu\n", DllType2String(dlltype).c_str(), value);cofs.WriteBuffer(&value, sizeof(unsigned long));return cofs;}friend TDllStream &operator<<(TDllStream &cofs, long long value) {DLL_WRITE(DRGRAPH_DLL_TYPE_LONGLONG);if (cbw_debug_flag)OS::get_singleton()->print("[DllStream] > 写入[%s]类型 > %lld\n", DllType2String(dlltype).c_str(), value);cofs.WriteBuffer(&value, sizeof(long long));return cofs;}friend TDllStream &operator<<(TDllStream &cofs, unsigned long long value) {DLL_WRITE(DRGRAPH_DLL_TYPE_ULONGLONG);if (cbw_debug_flag)OS::get_singleton()->print("[DllStream] > 写入[%s]类型 > %llu\n", DllType2String(dlltype).c_str(), value);cofs.WriteBuffer(&value, sizeof(unsigned long long));return cofs;}friend TDllStream &operator<<(TDllStream &cofs, float value) {//DLL_WRITE(DRGRAPH_DLL_TYPE_DOUBLE);double d = value;cofs << d;return cofs;}friend TDllStream &operator<<(TDllStream &cofs, double value) {DLL_WRITE(DRGRAPH_DLL_TYPE_DOUBLE);if (cbw_debug_flag)OS::get_singleton()->print("[DllStream] > 写入[%s]类型 > %s\n", DllType2String(dlltype).c_str(), Double2String(value, 3).c_str());cofs.WriteBuffer(&value, sizeof(double));return cofs;}friend TDllStream &operator<<(TDllStream &cofs, char *str) {std::string string = str;cofs << string;return cofs;}friend TDllStream &operator<<(TDllStream &cofs, const char *str) {std::string string = str;cofs << string;return cofs;}friend TDllStream &operator<<(TDllStream &cofs, const char32_t *str) {std::string result = String2std(str);cofs << result;return cofs;}friend TDllStream &operator<<(TDllStream &cofs, wchar_t *str) {std::string string = WChar2String(str);cofs << string;return cofs;}friend TDllStream &operator<<(TDllStream &cofs, const wchar_t *str) {std::string string = WChar2String(str);cofs << string;return cofs;}friend TDllStream &operator<<(TDllStream &cofs, std::string value);friend TDllStream &operator<<(TDllStream &cofs, String str) {std::string string = String2std(str);cofs << string;return cofs;}friend TDllStream &operator<<(TDllStream &cofs, TDllData &data) {if (data.type == DRGRAPH_DLL_TYPE_STRING)cofs << data.value_string;else if (data.type == DRGRAPH_DLL_TYPE_INT)cofs << data.value.value_int;else if (data.type == DRGRAPH_DLL_TYPE_DOUBLE)cofs << data.value.value_double;else if (data.type == DRGRAPH_DLL_TYPE_BOOL)cofs << data.value.value_bool;else if (data.type == DRGRAPH_DLL_TYPE_UCHAR)cofs << data.value.value_uchar;else if (data.type == DRGRAPH_DLL_TYPE_CHAR)cofs << data.value.value_char;else if (data.type == DRGRAPH_DLL_TYPE_WCHAR)cofs << data.value.value_wchar;else if (data.type == DRGRAPH_DLL_TYPE_SHORT)cofs << data.value.value_short;else if (data.type == DRGRAPH_DLL_TYPE_LONG)cofs << data.value.value_long;else if (data.type == DRGRAPH_DLL_TYPE_USHORT)cofs << data.value.value_ushort;else if (data.type == DRGRAPH_DLL_TYPE_UINT)cofs << data.value.value_uint;else if (data.type == DRGRAPH_DLL_TYPE_ULONG)cofs << data.value.value_ulong;else if (data.type == DRGRAPH_DLL_TYPE_LONGLONG)cofs << data.value.value_longlong;else if (data.type == DRGRAPH_DLL_TYPE_ULONGLONG)cofs << data.value.value_ulonglong;else if (data.type == DRGRAPH_DLL_TYPE_NULL)cofs.Finish();return cofs;}friend TDllStream &operator>>(TDllStream &cifs, bool &q) {unsigned char b;cifs >> b;q = b;return cifs;}friend TDllStream &operator>>(TDllStream &cifs, char &q) {cifs.ReadBuffer(&q, sizeof(char));return cifs;}friend TDllStream &operator>>(TDllStream &cifs, signed char &q) {cifs.ReadBuffer(&q, sizeof(signed char));return cifs;}friend TDllStream &operator>>(TDllStream &cifs, unsigned char &q) {cifs.ReadBuffer(&q, sizeof(unsigned char));return cifs;}friend TDllStream &operator>>(TDllStream &cifs, signed short &q) {cifs.ReadBuffer(&q, sizeof(signed short));return cifs;}friend TDllStream &operator>>(TDllStream &cifs, unsigned short &q) {cifs.ReadBuffer(&q, sizeof(unsigned short));return cifs;}friend TDllStream &operator>>(TDllStream &cifs, signed int &q) {cifs.ReadBuffer(&q, sizeof(signed int));return cifs;}friend TDllStream &operator>>(TDllStream &cifs, unsigned int &q) {cifs.ReadBuffer(&q, sizeof(unsigned int));return cifs;}friend TDllStream &operator>>(TDllStream &cifs, signed long &q) {cifs.ReadBuffer(&q, sizeof(signed long));return cifs;}friend TDllStream &operator>>(TDllStream &cifs, unsigned long &q) {cifs.ReadBuffer(&q, sizeof(unsigned long));return cifs;}friend TDllStream &operator>>(TDllStream &cifs, float &q) {cifs.ReadBuffer(&q, sizeof(float));return cifs;}friend TDllStream &operator>>(TDllStream &cifs, double &q) {cifs.ReadBuffer(&q, sizeof(double));return cifs;}friend TDllStream &operator>>(TDllStream &cifs, long double &q) {cifs.ReadBuffer(&q, sizeof(long double));return cifs;}friend TDllStream &operator>>(TDllStream &cifs, std::string &q);friend TDllStream &operator>>(TDllStream &cifs, TDllData &data) {if (data.type == DRGRAPH_DLL_TYPE_STRING)cifs >> data.value_string;else if (data.type == DRGRAPH_DLL_TYPE_INT)cifs.ReadBuffer(&data.value, sizeof(int));else if (data.type == DRGRAPH_DLL_TYPE_DOUBLE)cifs.ReadBuffer(&data.value, sizeof(double));else if (data.type == DRGRAPH_DLL_TYPE_BOOL)cifs.ReadBuffer(&data.value, sizeof(unsigned char));else if (data.type == DRGRAPH_DLL_TYPE_UCHAR)cifs.ReadBuffer(&data.value, sizeof(unsigned char));else if (data.type == DRGRAPH_DLL_TYPE_CHAR)cifs.ReadBuffer(&data.value, sizeof(char));else if (data.type == DRGRAPH_DLL_TYPE_WCHAR)cifs.ReadBuffer(&data.value, sizeof(wchar_t));else if (data.type == DRGRAPH_DLL_TYPE_SHORT)cifs.ReadBuffer(&data.value, sizeof(short));else if (data.type == DRGRAPH_DLL_TYPE_LONG)cifs.ReadBuffer(&data.value, sizeof(long));else if (data.type == DRGRAPH_DLL_TYPE_USHORT)cifs.ReadBuffer(&data.value, sizeof(unsigned short));else if (data.type == DRGRAPH_DLL_TYPE_UINT)cifs.ReadBuffer(&data.value, sizeof(unsigned int));else if (data.type == DRGRAPH_DLL_TYPE_ULONG)cifs.ReadBuffer(&data.value, sizeof(unsigned long));else if (data.type == DRGRAPH_DLL_TYPE_LONGLONG)cifs.ReadBuffer(&data.value, sizeof(long long));else if (data.type == DRGRAPH_DLL_TYPE_ULONG)cifs.ReadBuffer(&data.value, sizeof(unsigned long long));else if (data.type == DRGRAPH_DLL_TYPE_NULL)return cifs;return cifs;}
};
extern TDllData READING_DLL_DATA;#define DRGRAPH_SOURCE_POS str_format("%s[%d] - %S()", \std::string(__FILE__), __LINE__, __func__)#define GET_DLL_DATA(T, varName, is)                                                                                                 \READING_DLL_DATA = (is)->Next();                                                                                                 \T varName;                                                                                                                       \if (READING_DLL_DATA.type != DRGRAPH_DLL_TYPE_NULL) {                                                                            \if (READING_DLL_DATA.IsEof()) {                                                                                              \std::string msg = str_format("越界读取〖%S %S; > @%s〗,请检查协议...", typeid(T).name(), #varName, DRGRAPH_SOURCE_POS); \throw(msg);                                                                                                              \}                                                                                                                            \varName = READING_DLL_DATA;                                                                                                  \}class TCbwPipe {void *g_hNamedPipe; // 管道句柄bool CreateNamePipeC(const char *iPipeName); // 创建命名管道客户端std::string FPipeServerName;static TCbwPipe *singleton;public:void ReadPipeData(BYTE *iBuffer, int &iBufferSize, int timeout = 1000); // 读取数据bool WriteDllStream(TDllStream &os, int timeout = 1000);public:TCbwPipe();~TCbwPipe();bool ConnectToServer(std::string pipeServerName);static TCbwPipe *get_singleton();static void Free();
};std::string String2std(String str);
#include "CbwPipe.h"#include <stdarg.h>
#include <thread>#include <locale.h>
#include <windows.h>
#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
#include <codecvt>std::string String2std(String str) {//std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;//std::string result = converter.to_bytes(str.ptr());wchar_t *wchar = char32ToWchar(str.ptr());std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;std::string result = converter.to_bytes(wchar);delete[] wchar;return result;
}wchar_t *char32ToWchar(const char32_t *char32Str) {std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;// 将 char32_t* 转换为 UTF-8 编码的 std::stringstd::string utf8Str = converter.to_bytes(char32Str);// 计算宽字符字符串所需的长度size_t wideLen = mbstowcs(nullptr, utf8Str.c_str(), 0) + 1;// 分配内存并转换为宽字符字符串wchar_t *wcharStr = new wchar_t[wideLen];mbstowcs(wcharStr, utf8Str.c_str(), wideLen);return wcharStr;
}TDllStream& operator<<(TDllStream& cofs, std::string value) {DLL_WRITE(DRGRAPH_DLL_TYPE_STRING);if (cbw_debug_flag)OS::get_singleton()->print("[DllStream] > 写入[%s]类型 > %s\n", DllType2String(dlltype).c_str(), value.c_str());int wideCharLen = MultiByteToWideChar(CP_UTF8, 0, value.c_str(), value.length() + 1, nullptr, 0);wchar_t *wideCharStr = new wchar_t[wideCharLen];int multiByteLen = WideCharToMultiByte(CP_UTF8, 0, wideCharStr, wideCharLen, nullptr, 0, nullptr, nullptr);char *multiByteStr = new char[multiByteLen];WideCharToMultiByte(CP_UTF8, 0, wideCharStr, wideCharLen, multiByteStr, multiByteLen, nullptr, nullptr);cofs.WriteBuffer(&multiByteLen, sizeof(int));cofs.WriteBuffer((void *)multiByteStr, multiByteLen);delete[] wideCharStr;delete[] multiByteStr;return cofs;
}bool cbw_debug_flag = true;TDllStream &operator>>(TDllStream &cifs, std::string &q) {int length;cifs >> length;char *chBuffer = new char[length + 1];cifs.ReadBuffer(chBuffer, length);int wLength = length + 1;wchar_t *wcBuffer = new wchar_t[wLength];MultiByteToWideChar(CP_UTF8, 0, chBuffer, wLength, wcBuffer, wLength);q = WChar2String(wcBuffer);delete wcBuffer;delete chBuffer;return cifs;
}
template <typename... Args>
static std::string str_format(const std::string &format, Args... args) {auto size_buf = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;std::unique_ptr<char[]> buf(new (std::nothrow) char[size_buf]);if (!buf)return std::string("");std::snprintf(buf.get(), size_buf, format.c_str(), args...);return std::string(buf.get(), buf.get() + size_buf - 1);
}std::string Double2String(double value, int maxBits, int fixedFlag, int width) {std::string result = str_format("%f", value);size_t pointPos = result.find(".");if (pointPos > 0) {size_t floatNumber = result.length() - pointPos;if (floatNumber > maxBits)result.erase(pointPos + maxBits + 1, result.length());if (pointPos == 0)result = str_format("0%s", result);}for (size_t i = result.length() - 1; i >= 0; --i) {if (result.c_str()[i] == '0')result.erase(i + 1, 1);elsebreak;}if (result.length() > 0 && result.c_str()[result.length() - 1] == L'.')result.erase(result.length(), 1);if (fixedFlag) {size_t pointPos = result.find(".");if (pointPos == result.npos) {result += ".";pointPos = result.length();}int floatNumber = result.length() - pointPos;while (floatNumber++ < maxBits)result += "0";}int blankNumber = width - result.length();if (blankNumber > 0) {std::string pre;pre.resize(blankNumber, ' ');result = pre + result;}return result;
}std::string WChar2String(wchar_t *pwszSrc) {int nLen = WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, NULL, 0, NULL, NULL);if (nLen <= 0)return std::string("");char *pszDst = new char[nLen];if (NULL == pszDst)return std::string("");WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, pszDst, nLen, NULL, NULL);pszDst[nLen - 1] = 0;std::string strTemp(pszDst);delete[] pszDst;return strTemp;
}std::string WChar2String(const wchar_t *pwszSrc) {return WChar2String(const_cast<wchar_t *>(pwszSrc));
}std::string DllType2String(unsigned char type) {std::string result = type == DRGRAPH_DLL_TYPE_NULL ? "结束": type == DRGRAPH_DLL_TYPE_BOOL			   ? "bool": type == DRGRAPH_DLL_TYPE_CHAR			   ? "char": type == DRGRAPH_DLL_TYPE_UCHAR		   ? "BYTE": type == DRGRAPH_DLL_TYPE_WCHAR		   ? "wchar_t": type == DRGRAPH_DLL_TYPE_SHORT		   ? "short": type == DRGRAPH_DLL_TYPE_USHORT		   ? "unsigned short": type == DRGRAPH_DLL_TYPE_INT			   ? "int": type == DRGRAPH_DLL_TYPE_UINT			   ? "unsigned int": type == DRGRAPH_DLL_TYPE_LONG			   ? "long": type == DRGRAPH_DLL_TYPE_ULONG		   ? "unsigned long": type == DRGRAPH_DLL_TYPE_DOUBLE		   ? "double": type == DRGRAPH_DLL_TYPE_STRING		   ? "string": type == DRGRAPH_DLL_TYPE_LONGLONG		   ? "long long": type == DRGRAPH_DLL_TYPE_ULONGLONG	   ? "unsigned long long": "未知类型";return result;
}std::string VarType2String(Variant::Type t) {switch (t) {case Variant::NIL:return "NIL";case Variant::BOOL:return "BOOL";case Variant::INT:return "INT";case Variant::FLOAT:return "FLOAT";case Variant::STRING:return "STRING";case Variant::VECTOR2:return "VECTOR2";case Variant::VECTOR2I:return "VECTOR2I";case Variant::RECT2:return "RECT2";case Variant::RECT2I:return "RECT2I";case Variant::VECTOR3:return "VECTOR3";case Variant::VECTOR3I:return "VECTOR3I";case Variant::TRANSFORM2D:return "TRANSFORM2D";case Variant::VECTOR4:return "VECTOR4";case Variant::VECTOR4I:return "VECTOR4I";case Variant::PLANE:return "PLANE";case Variant::QUATERNION:return "QUATERNION";case Variant::AABB:return "AABB";case Variant::BASIS:return "BASIS";case Variant::TRANSFORM3D:return "TRANSFORM3D";case Variant::PROJECTION:return "PROJECTION";case Variant::COLOR:return "COLOR";case Variant::STRING_NAME:return "STRING_NAME";case Variant::NODE_PATH:return "NODE_PATH";case Variant::RID:return "RID";case Variant::OBJECT:return "OBJECT";case Variant::CALLABLE:return "CALLABLE";case Variant::SIGNAL:return "SIGNAL";case Variant::DICTIONARY:return "DICTIONARY";case Variant::ARRAY:return "ARRAY";case Variant::PACKED_BYTE_ARRAY:return "PACKED_BYTE_ARRAY";case Variant::PACKED_INT32_ARRAY:return "PACKED_INT32_ARRAY";case Variant::PACKED_INT64_ARRAY:return "PACKED_INT64_ARRAY";case Variant::PACKED_FLOAT32_ARRAY:return "PACKED_FLOAT32_ARRAY";case Variant::PACKED_FLOAT64_ARRAY:return "PACKED_FLOAT64_ARRAY";case Variant::PACKED_STRING_ARRAY:return "PACKED_STRING_ARRAY";case Variant::PACKED_VECTOR2_ARRAY:return "PACKED_VECTOR2_ARRAY";case Variant::PACKED_VECTOR3_ARRAY:return "PACKED_VECTOR3_ARRAY";case Variant::PACKED_COLOR_ARRAY:return "PACKED_COLOR_ARRAY";case Variant::VARIANT_MAX:return "VARIANT_MAX";default:return "UNKNOWN";}
}TDllData READING_DLL_DATA;TDllData::TDllData(unsigned char t) {type = t;
}TDllData::TDllData(const TDllData &copy) {type = copy.type;value = copy.value;value_string = copy.value_string;
}TDllData::~TDllData() {
}std::string TDllData::GetHint() {std::string result = str_format("[%s]类型 > 值 = ", DllType2String(type));result += type == DRGRAPH_DLL_TYPE_BOOL		 ? (value.value_bool ? "true" : "false"): type == DRGRAPH_DLL_TYPE_CHAR		 ? str_format("%d[0X%02X, %c]", value.value_char, value.value_char, value.value_char): type == DRGRAPH_DLL_TYPE_UCHAR	 ? str_format("%d[0X%02X, %c]", value.value_uchar, value.value_uchar, value.value_uchar): type == DRGRAPH_DLL_TYPE_WCHAR	 ? str_format("%lc", value.value_wchar): type == DRGRAPH_DLL_TYPE_SHORT	 ? str_format("%d", value.value_short): type == DRGRAPH_DLL_TYPE_USHORT	 ? str_format("%d", value.value_ushort): type == DRGRAPH_DLL_TYPE_INT		 ? str_format("%d", value.value_int): type == DRGRAPH_DLL_TYPE_UINT		 ? str_format("%d", value.value_uint): type == DRGRAPH_DLL_TYPE_LONG		 ? str_format("%ld", value.value_long): type == DRGRAPH_DLL_TYPE_ULONG	 ? str_format("%lu", value.value_ulong): type == DRGRAPH_DLL_TYPE_LONGLONG	 ? str_format("%lld", value.value_longlong): type == DRGRAPH_DLL_TYPE_ULONGLONG ? str_format("%llu", value.value_ulonglong): type == DRGRAPH_DLL_TYPE_DOUBLE	 ? str_format("%s", Double2String(value.value_double, 3)): type == DRGRAPH_DLL_TYPE_STRING	 ? str_format("%s", value_string): str_format("已结束");return result;
}void TDllData::CheckType(unsigned char destType) {if (destType != type)OS::get_singleton()->print("类型不正确,转换可能会出现偏差,请检查协议 > 当前类型: %s, 目标类型: %s",DllType2String(type).c_str(), DllType2String(destType).c_str());
}TDllData *TDllData::operator=(const TDllData &equal) {type = equal.type;value = equal.value;value_string = equal.value_string;return this;
}TDllData::operator bool() {CheckType(DRGRAPH_DLL_TYPE_BOOL);return value.value_bool;
}TDllData::operator char() {CheckType(DRGRAPH_DLL_TYPE_CHAR);return value.value_char;
}TDllData::operator unsigned char() {CheckType(DRGRAPH_DLL_TYPE_UCHAR);return value.value_uchar;
}TDllData::operator wchar_t() {CheckType(DRGRAPH_DLL_TYPE_WCHAR);return value.value_wchar;
}TDllData::operator short() {CheckType(DRGRAPH_DLL_TYPE_SHORT);return value.value_short;
}TDllData::operator unsigned short() {CheckType(DRGRAPH_DLL_TYPE_USHORT);return value.value_ushort;
}TDllData::operator int() {CheckType(DRGRAPH_DLL_TYPE_INT);return value.value_int;
}TDllData::operator unsigned int() {CheckType(DRGRAPH_DLL_TYPE_UINT);return value.value_uint;
}TDllData::operator long() {CheckType(DRGRAPH_DLL_TYPE_LONG);return value.value_long;
}TDllData::operator unsigned long() {CheckType(DRGRAPH_DLL_TYPE_ULONG);return value.value_ulong;
}TDllData::operator long long() {CheckType(DRGRAPH_DLL_TYPE_LONGLONG);return value.value_longlong;
}TDllData::operator unsigned long long() {CheckType(DRGRAPH_DLL_TYPE_ULONGLONG);return value.value_ulonglong;
}TDllData::operator double() {CheckType(DRGRAPH_DLL_TYPE_DOUBLE);return value.value_double;
}TDllData::operator std::string() {CheckType(DRGRAPH_DLL_TYPE_STRING);return value_string;
}void TDllStream::SetPointer(void *pMemory, int nSize) {m_pMemory = (char *)pMemory;m_nSize = nSize;
}void TDllStream::SetMemoryDelta(int nNewMemoryDelta) {if (nNewMemoryDelta != DEFAULT_MEMORY_DELTA) {if (nNewMemoryDelta < MIN_MEMORY_DELTA)nNewMemoryDelta = MIN_MEMORY_DELTA;// 2^Nfor (int i = sizeof(int) * 8 - 1; i >= 0; i--)if (((1 << i) & nNewMemoryDelta) != 0) {nNewMemoryDelta &= (1 << i);break;}}m_nMemoryDelta = nNewMemoryDelta;
}void TDllStream::SetCapacity(int nNewCapacity) {SetPointer(Realloc(nNewCapacity), m_nSize);m_nCapacity = nNewCapacity;
}char *TDllStream::Realloc(int &nNewCapacity) {char *pResult;if (nNewCapacity > 0 && nNewCapacity != m_nSize)nNewCapacity = (nNewCapacity + (m_nMemoryDelta - 1)) & ~(m_nMemoryDelta - 1);pResult = m_pMemory;if (nNewCapacity != m_nCapacity) {if (nNewCapacity == 0) {free(m_pMemory);pResult = NULL;} else {if (m_nCapacity == 0)pResult = (char *)malloc(nNewCapacity);elsepResult = (char *)realloc(m_pMemory, nNewCapacity);}}return pResult;
}int TDllStream::GetSize() const {int nPos, nResult;nPos = const_cast<TDllStream &>(*this).Seek(0, SO_CURRENT);nResult = const_cast<TDllStream &>(*this).Seek(0, SO_END);const_cast<TDllStream &>(*this).Seek(nPos, SO_BEGINNING);return nResult;
}void TDllStream::SetSize(int nSize) {int nOldPos = m_nPosition;SetCapacity((int)nSize);m_nSize = (int)nSize;if (nOldPos > nSize)Seek(0, SO_END);
}int TDllStream::GetPosition() const {return const_cast<TDllStream &>(*this).Seek(0, SO_CURRENT);
}void TDllStream::SetPosition(int nPos) {Seek(nPos, SO_BEGINNING);
}int TDllStream::Read(void *pBuffer, int nCount) {int nResult = 0;if (m_nPosition >= 0 && nCount >= 0) {nResult = m_nSize - m_nPosition;if (nResult > 0) {if (nResult > nCount)nResult = nCount;memmove(pBuffer, m_pMemory + (DWORD)m_nPosition, nResult);m_nPosition += nResult;}}return nResult;
}int TDllStream::Write(const void *pBuffer, int nCount) {int nResult = 0;int nPos;if (m_nPosition >= 0 && nCount >= 0) {nPos = m_nPosition + nCount;if (nPos > 0) {if (nPos > m_nSize) {if (nPos > m_nCapacity)SetCapacity(nPos);m_nSize = nPos;}memmove(m_pMemory + (DWORD)m_nPosition, pBuffer, nCount);m_nPosition = nPos;nResult = nCount;}}return nResult;
}TDllStream::TDllStream(BYTE *datas, int len) :m_nCapacity(0), m_pMemory(NULL), m_nSize(0), m_nPosition(0) {SetMemoryDelta(DEFAULT_MEMORY_DELTA);Clear();WriteBuffer(datas, len);Finished = false;Rewind();
}TDllStream::~TDllStream() {Clear();
}int TDllStream::Seek(int nOffset, SEEK_ORIGIN nSeekOrigin) {switch (nSeekOrigin) {case SO_BEGINNING:m_nPosition = (int)nOffset;break;case SO_CURRENT:m_nPosition += (int)nOffset;break;case SO_END:m_nPosition = m_nSize + (int)nOffset;break;}return m_nPosition;
}bool TDllStream::ReadBuffer(void *pBuffer, int nCount) {if (nCount != 0 && Read(pBuffer, nCount) != nCount)return false;elsereturn true;
}bool TDllStream::WriteBuffer(void *pBuffer, int nCount) {if (nCount != 0 && Write(pBuffer, nCount) != nCount)return false;elsereturn true;
}void TDllStream::Clear() {SetCapacity(0);m_nSize = 0;m_nPosition = 0;
}bool TDllStream::IsEOF() {return Position >= Size;
}void TDllStream::Rewind() {Position = 0;
}void TDllStream::Finish() {unsigned short value = DRGRAPH_DLL_TYPE_NULL;WriteBuffer(&value, sizeof(unsigned short));Finished = true;
}TDllData TDllStream::Next() {unsigned char type;bool readed = ReadBuffer(&type, sizeof(unsigned char));TDllData result(type);if (readed)(*this) >> result;return result;
}void TDllStream::Reset() {Clear();
}int TDllStream::NextFunType() {if (Size - Position <= 2)return 0;GET_DLL_DATA(int, funType, this);if (READING_DLL_DATA.type == DRGRAPH_DLL_TYPE_NULL)funType = DRSTREAM_FUNCTION_NONE;return funType;
}TDllStream::operator BYTE *() {Position = 0;int len = Size;BYTE *result = new BYTE[len];ReadBuffer(result, len);Position = 0;return result;
}TCbwPipe *TCbwPipe::singleton = nullptr;
TCbwPipe *TCbwPipe::get_singleton() {if (!TCbwPipe::singleton) {TCbwPipe::singleton = new TCbwPipe();}return TCbwPipe::singleton;
}void TCbwPipe::Free() {if (TCbwPipe::singleton)delete TCbwPipe::singleton;TCbwPipe::singleton = NULL;
}TCbwPipe::TCbwPipe() {setlocale(LC_ALL, "");g_hNamedPipe = INVALID_HANDLE_VALUE;
}TCbwPipe::~TCbwPipe() {if (g_hNamedPipe != INVALID_HANDLE_VALUE && g_hNamedPipe != NULL)CloseHandle(g_hNamedPipe);
}bool TCbwPipe::CreateNamePipeC(const char *iPipeName) {char t_PipeName[200];//1,创建一个命名管道sprintf_s(t_PipeName, "\\\\.\\pipe\\%s", iPipeName);if (WaitNamedPipeA(t_PipeName, NMPWAIT_WAIT_FOREVER) == 0) {OS::get_singleton()->print("当前没有可以利用的管道:%d\n", GetLastError());return false;}g_hNamedPipe = CreateFileA(t_PipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (g_hNamedPipe == INVALID_HANDLE_VALUE) {OS::get_singleton()->print("打开命名管道失败!:%d\n", GetLastError());g_hNamedPipe = NULL;return false;}OS::get_singleton()->print("链接管道%s已成功\n", t_PipeName);return true;
}
#include <iomanip>
#include <iostream>
#include <sstream>
// 读取数据
void TCbwPipe::ReadPipeData(BYTE *iBuffer, int &iBufferSize, int timeout) {DWORD availableBytes;if (g_hNamedPipe == INVALID_HANDLE_VALUE) {OS::get_singleton()->is_pipe_allowed = false;return;}if (!PeekNamedPipe(g_hNamedPipe, NULL, 0, NULL, &availableBytes, NULL)) {OS::get_singleton()->print("[Pipe.Read] > 读取数据失败:%d\n", GetLastError());if (g_hNamedPipe != INVALID_HANDLE_VALUE && g_hNamedPipe != NULL)CloseHandle(g_hNamedPipe);g_hNamedPipe = INVALID_HANDLE_VALUE;OS::get_singleton()->is_pipe_allowed = false;return;}if (availableBytes < 1) {iBufferSize = 0;return;}//读取数据DWORD dwRead;HANDLE t_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);OVERLAPPED ovlap;ZeroMemory(&ovlap, sizeof(OVERLAPPED));ovlap.hEvent = t_hEvent;if (ReadFile(g_hNamedPipe, iBuffer, iBufferSize, &dwRead, &ovlap) == false) {OS::get_singleton()->print("[Pipe.Read] > 读取数据失败:%d\n", GetLastError());if (t_hEvent)CloseHandle(t_hEvent);t_hEvent = NULL;iBufferSize = 0;return;}iBufferSize = 0;if (t_hEvent) {bool failed = (WaitForSingleObject(t_hEvent, timeout) == WAIT_FAILED);CloseHandle(t_hEvent);t_hEvent = NULL;if (failed) {OS::get_singleton()->print("[Pipe.Read] > 等待对象失败:%d\n", GetLastError());return;}}if (dwRead > 0) {iBufferSize = dwRead;std::ostringstream oss{};//oss << "[Pipe.Read] > 接收到数据: ";for (DWORD i = 0; i < dwRead; ++i)oss << std::hex << iBuffer[i] << ", ";oss << std::endl;std::string str = oss.str();OS::get_singleton()->print("[Pipe.Read] > 接收到数据: %s\n", str.c_str());TDllStream cifs(iBuffer, dwRead);do {int funType = cifs.NextFunType();if (funType == DRSTREAM_FUNCTION_NONE)break;if (funType == DRSTREAM_FUNCTION_STATUS) {READING_DLL_DATA = cifs.Next();std::string status = READING_DLL_DATA;READING_DLL_DATA = cifs.Next();std::string value = READING_DLL_DATA;OS::get_singleton()->print("[Pipe.Read] > funType = %d > status = %s, value = %s\n", funType, status.c_str(), value.c_str());}} while (true);//ConnectToServer(FPipeServerName);}
}bool TCbwPipe::WriteDllStream(TDllStream &os, int timeout) {DWORD dwWrite;int len = os.Size + 1;BYTE *data = os;if (!WriteFile(g_hNamedPipe, data, len, &dwWrite, NULL)) {OS::get_singleton()->print("[Pipe.Error] > 写入数据失败:%d\n", GetLastError());delete data;return false;}delete data;return true;
}bool TCbwPipe::ConnectToServer(std::string pipeServerName) {FPipeServerName = pipeServerName;if (g_hNamedPipe != INVALID_HANDLE_VALUE && g_hNamedPipe != NULL)CloseHandle(g_hNamedPipe);g_hNamedPipe = INVALID_HANDLE_VALUE;const char *t_PipeName = pipeServerName.c_str();return CreateNamePipeC(t_PipeName);
}

实现过程没费劲,就是编译费劲。一直提示相应功能没有实现。原来godot是用scons什么工具编译的,需要配置路径什么的。为省事,避免琢磨scons,我把CbwPipe两个文件放在已有目录下就OK了。

GDScript支持

在源码中增加了功能,肯定是希望在godot项目中使用,比如用GDScript编写脚本时可用

在CharGPT指导下,完成这个功能还算顺利。核心是与ClassDB打交道

class DllStream : public Object {GDCLASS(DllStream, Object);TDllStream stream;public:DllStream();DllStream *rewind();DllStream * write(const Variant **p_args, int p_argcount, Callable::CallError &r_error);void send_pipe();
};

DllStream::DllStream() {ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "write", &DllStream::write, MethodInfo("write"));ClassDB::bind_method(D_METHOD("rewind"), &DllStream::rewind);ClassDB::bind_method(D_METHOD("send_pipe"), &DllStream::send_pipe);
}DllStream * DllStream::write(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {for (int i = 0; i < p_argcount; ++i) {print_line("DllStream::write(", i + 1, "/", p_argcount, ": type = ", p_args[i]->get_type_name(p_args[i]->get_type()), ", value = ", *p_args[i]);switch (p_args[i]->get_type()) {case Variant::BOOL:stream << bool(p_args[i]);break;case Variant::INT:stream << int(*p_args[i]);break;case Variant::FLOAT:stream << float(*p_args[i]);break;case Variant::STRING:stream << String(*p_args[i]).ptr();		// todo: char32_t的处理break;}}return this;
}DllStream* DllStream::rewind() {stream.Rewind();return this;
}void DllStream::send_pipe() {TCbwPipe::get_singleton()->WriteDllStream(stream);
}

在godot启动过程中,直接自动发一些管道信息:

std::string pipeName = String2std(p);
OS::get_singleton()->is_pipe_allowed = TCbwPipe::get_singleton()->ConnectToServer(pipeName);
TDllStream dsSet, dsGet;
dsSet << DRSTREAM_FUNCTION_SET<< "MainForm"<< "Caption"<< "godot 标题 Command by DrGraph"<< ioFinish;
dsGet << DRSTREAM_FUNCTION_GET<< "CurrentForm"<< "Caption" << ioFinish;
TCbwPipe::get_singleton()->WriteDllStream(dsSet);
TCbwPipe::get_singleton()->WriteDllStream(dsGet);

在DrGraph软件中接收到管道数据:

 GDScript注册

为了在GDScript中使用,还需要注册类名

GDREGISTER_CLASS(DllStream);

在Script编辑器中,就可以出现代码提示了

相应功能调用

 Godot工程运行后,在界面中操作以触发相应代码功能

 使用触发后,在Godot软件中可看到输出

 DrGraph软件中同步收到管道信息

 达到效果。还有一点小问题,中文乱码,应该是编解码问题,有空再处理一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/6575.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pytorch迁移学习使用Resnet50进行模型训练预测猫狗二分类

目录 1.ResNet残差网络 1.1 ResNet定义 1.2 ResNet 几种网络配置 1.3 ResNet50网络结构 1.3.1 前几层卷积和池化 1.3.2 残差块&#xff1a;构建深度残差网络 1.3.3 ResNet主体&#xff1a;堆叠多个残差块 1.4 迁移学习猫狗二分类实战 1.4.1 迁移学习 1.4.2 模型训练 1.…

华为数通HCIP-ISIS基础

IS-IS的基本概念 isis&#xff08;中间系统到中间路由协议&#xff09; 链路状态路由协议、IGP、无类路由协议&#xff1b; IS-IS是一种链路状态路由协议&#xff0c;IS-IS与OSPF在许多方面非常相似:运行IS-IS协议的直连设备之间通过发送Hello报文发现彼此&#xff0c;然后建…

从零开始搭建vue3 + ts + pinia + vite +element-plus项目

前言&#xff1a;据说vue2将于 2023 年 12 月 31 日停止维护&#xff0c;最近打算搭建一个vue3项目来学习一下&#xff0c;以防忘记&#xff0c;记录一下搭建过程。 一、使用npm创建项目 前提条件&#xff1a;已安装 16.0 或更高版本的 Node.js 执行 “npm init vuelatest”…

【Java基础教程】(四十三)多线程篇 · 下:深入剖析Java多线程编程:同步、死锁及经典案例——生产者与消费者,探究sleep()与wait()的差异

Java基础教程之多线程 下 &#x1f539;本节学习目标1️⃣ 线程的同步与死锁1.1 同步问题的引出2.2 synchronized 同步操作2.3 死锁 2️⃣ 多线程经典案例——生产者与消费者&#x1f50d;分析sleep()和wait()的区别&#xff1f; &#x1f33e; 总结 &#x1f539;本节学习目标…

谷歌插件(Chrome扩展) “Service Worker (无效)” 解决方法

问题描述&#xff1a; 写 background 文件的时候报错了&#xff0c;说 Service Worker 设置的 background 无效。 解决&#xff08;检查&#xff09;方法&#xff1a; 检查配置文件&#xff08;manifest.json&#xff09; 中的 manifest_version 是否为 3。 background 中的…

如何动态修改 spring aop 切面信息?让自动日志输出框架更好用

业务背景 很久以前开源了一款 auto-log 自动日志打印框架。 其中对于 spring 项目&#xff0c;默认实现了基于 aop 切面的日志输出。 但是发现一个问题&#xff0c;如果切面定义为全切范围过大&#xff0c;于是 v0.2 版本就是基于注解 AutoLog 实现的。 只有指定注解的类或…

DataWhale AI夏令营——机器学习

DataWhale AI夏令营——机器学习 学习记录一1. 异常值分析2. 单变量箱线图可视化3. 特征重要性分析 学习记录一 锂电池电池生产参数调控及生产温度预测挑战赛 已配置环境&#xff0c;跑通baseline&#xff0c;并在此基础上对数据进行了简单的分析。 1. 异常值分析 对训练集…

K8S初级入门系列之八-网络

一、前言 本章节我们将了解K8S的相关网络概念&#xff0c;包括K8S的网络通讯原理&#xff0c;以及Service以及相关的概念&#xff0c;包括Endpoint&#xff0c;EndpointSlice&#xff0c;Headless service&#xff0c;Ingress等。 二、网络通讯原理和实现 同一K8S集群&…

PMP 数据收集工具与技术

数据收集工具与技术 (9个) 标杆对照 标杆对照是指将实际或计划的产品、流程和实践与其他可比组织的 做法进行比较&#xff0c;以便识别最佳实践、形成改进意见&#xff0c;并为绩效考核 提供依据。 头脑风暴 头脑风暴是一种数据收集和创意技术&#xff0c;主要用于在短时间…

三维点云中的坐标变换(只讲关键部分)

一、坐标旋转 坐标旋转包含绕x、y、z轴旋转&#xff0c;在右手坐标系中&#xff0c;x-翻滚(roll)&#xff0c;y-俯仰(pitch)&#xff0c;z-航向(yaw)。如果想详细了解&#xff0c;可以网络搜索 在PCL中&#xff0c;从baseLink到map的转换关系为:先绕x轴旋转,在绕y轴旋转,最后绕…

【软件工程中的各种图】

1、用例图&#xff08;use case diagrams&#xff09; 【概念】描述用户需求&#xff0c;从用户的角度描述系统的功能 【描述方式】椭圆表示某个用例&#xff1b;人形符号表示角色 【目的】帮组开发团队以一种可视化的方式理解系统的功能需求 【用例图】 2、静态图(Static …

【数据结构】C--单链表(小白入门基础知识)

前段时间写了一篇关于顺序表的博客&#xff0c;http://t.csdn.cn/0gCRp 顺序表在某些时候存在着一些不可避免的缺点: 问题&#xff1a; 1. 中间 / 头部的插入删除&#xff0c;时间复杂度为 O(N) 2. 增容需要申请新空间&#xff0c;拷贝数据&#xff0c;释放旧空间。会有不…

前端 | ( 十一)CSS3简介及基本语法(上) | 尚硅谷前端html+css零基础教程2023最新

学习来源&#xff1a;尚硅谷前端htmlcss零基础教程&#xff0c;2023最新前端开发html5css3视频 系列笔记&#xff1a; 【HTML4】&#xff08;一&#xff09;前端简介【HTML4】&#xff08;二&#xff09;各种各样的常用标签【HTML4】&#xff08;三&#xff09;表单及HTML4收尾…

2023/07/23

1. 必须等待所有请求结束后才能执行后续操作的处理方式 方式一&#xff1a; async func () {const p1 await api1();const p2 await api2();const p3 await api3();Promise.all([p1, p2, p3]).then(res > {后续操作...}) }方式二&#xff1a;待补充 2. flex 弹性盒子布…

FPGA实现串口回环

文章目录 前言一、串行通信1、分类1、同步串行通信2、异步串行通信 2、UART串口通信1、UART通信原理2、串口通信时序图 二、系统设计1、系统框图2.RTL视图 三、源码1、串口发送模块2、接收模块3、串口回环模块4、顶层模块 四、测试效果五、总结六、参考资料 前言 环境&#xff…

【计算机视觉 | 目标检测】arxiv 计算机视觉关于目标检测的学术速递(7 月 21 日论文合集)

文章目录 一、检测相关(15篇)1.1 Representation Learning in Anomaly Detection: Successes, Limits and a Grand Challenge1.2 AlignDet: Aligning Pre-training and Fine-tuning in Object Detection1.3 Cascade-DETR: Delving into High-Quality Universal Object Detectio…

《Docker与持续集成/持续部署:构建高效交付流程,打造敏捷软件交付链》

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

c语言修炼之指针和数组笔试题解析(1.2)

前言&#xff1a; 书接上回&#xff0c;让我们继续开始今天的学习叭&#xff01;废话不多说&#xff0c;还是字符数组的内容上代码&#xff01; char *p是字符指针&#xff0c;*表示p是个指针&#xff0c;char表示p指向的对象类型是char型&#xff01; char*p"abcdef&q…

使用Plist编辑器——简单入门指南

本指南将介绍如何使用Plist编辑器。您将学习如何打开、编辑和保存plist文件&#xff0c;并了解plist文件的基本结构和用途。跟随这个简单的入门指南&#xff0c;您将掌握如何使用Plist编辑器轻松管理您的plist文件。 plist文件是一种常见的配置文件格式&#xff0c;用于存储应…

7.6Java EE——Bean的生命周期

Bean在不同作用域内的生命周期 Bean的生命周期是指Bean实例被创建、初始化和销毁的过程。在Bean的两种作用域singleton和prototype中&#xff0c;Spring容器对Bean的生命周期的管理是不同的。在singleton作用域中&#xff0c;Spring容器可以管理Bean的生命周期&#xff0c;控制…