学习研究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 ©);~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 ©) {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软件中同步收到管道信息
达到效果。还有一点小问题,中文乱码,应该是编解码问题,有空再处理一下。