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

文章介绍了在Godot4中使用C++实现命名管道通信的详细过程,包括TDllStream类的设计,以及如何与自定义的DrGraph软件进行数据交换。此外,还展示了Godot端的GDScript绑定,以便在游戏引擎中使用该通信机制。

学习研究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);
//#endif

	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)
			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;
		} else
			q = 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;     		// varShortInt
		case 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 3

typedef 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);
	
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值