仔细看了一下。。。许久没有更新这里了。。。多数时间是写网易那个。。。荒废了这里也不好。。。
一直在公司用同事写的log窗口用惯了。。。回到家里发现没得用。。。还真是不习惯。。。
现在实在是不大想调试。。。所以。。。还是秉着自己动手丰衣足食的方针。。。。自己写一个吧。。。
也是用mailslot。。。翻了一下API。。马上就动手写。。。因为想要一个能支持宽字符的。。。
所以仿windows似的写了两个函数。。。然后再用宏定义一下。。。
#include "stdafx.h" #include <stdarg.h> namespace JerryUtils { #include <stdio.h> #include <windows.h> static const size_t c_buf_size = 2046; // the first two byte use to indicate the coding // if 0x0000 is multip bytes coding void __cdecl msglogA(const char * str_, va_list va_) { char temp[c_buf_size] = {0}; int print_len = _vsnprintf(temp + 2, c_buf_size - 2, str_, va_); if(print_len < 0) { strcpy(temp, "over flow"); print_len = strlen("over flow") * sizeof(char); } HANDLE temp_handle = CreateFileA("////.//Mailslot//snowlog", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(temp_handle != INVALID_HANDLE_VALUE) { DWORD write_byte = 0; WriteFile(temp_handle, temp, print_len, &write_byte, NULL); } } // if 0xFFFF is unicode coding void __cdecl msglogW(const wchar_t * str_, va_list va_) { wchar_t temp[c_buf_size] = {0xFFFF}; int print_len = _vsnwprintf(temp + 1, c_buf_size - 1, str_, va_); if(print_len < 0) { wcscpy(temp, L"over flow"); print_len = wcslen(L"over flow") * sizeof(wchar_t); } HANDLE temp_handle = CreateFileW(L"////.//Mailslot//snowlog", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(temp_handle != INVALID_HANDLE_VALUE) { DWORD write_byte = 0; WriteFile(temp_handle, temp, print_len * sizeof(wchar_t), &write_byte, NULL); } } }; void _cdecl msglogA(const char * str_, ...) { va_list va; va_start(va, str_); JerryUtils::msglogA(str_, va); va_end(va); } void __cdecl msglogW(const unsigned short * str_, ...) { va_list va; va_start(va, str_); JerryUtils::msglogW(str_, va); va_end(va); }
这里用namespace包一下。。然后再定义一个转发。。纯粹是吃饱撑着没事干故意写成这样的。。。
实际上在这里这样处理是没有太大意义的。。。。
上次同事和我讲了一下在V8代码里面一个实现。。。。用一个非常惊为天人的手法去掉了pimp模式的那个指针。。。。
令我记忆犹新。。。所以写的时候不知不觉也写成这样了。。。。
log窗口部分的代码实际上也是比较简单。。。从mailslot收。。。然后显示出来而已。。。
BOOL CSnowListWndDlg::OnInitDialog() { // other MFC code.......... m_last_msg = false; mailslot_handle = CreateMailslot(_T("////.//Mailslot//snowlog"), 0, MAILSLOT_WAIT_FOREVER, NULL); AfxBeginThread(MyThreadFunc, this); // other MFC code....... } static UINT MyThreadFunc(LPVOID pParam) { CSnowListWndDlg * ptr = static_cast<CSnowListWndDlg*>(pParam); ptr->ReceiveData(); return 0; } void CSnowListWndDlg::OnDestroy() { CDialog::OnDestroy(); m_last_msg = true; SendLastMsg(); } void CSnowListWndDlg::ReceiveData() { DWORD msg_len = 0; DWORD msg_count = 0; while(GetMailslotInfo(mailslot_handle, NULL, &msg_len, &msg_count, NULL) != 0) { if(msg_len == MAILSLOT_NO_MESSAGE) Sleep(10); else { vector<unsigned char> temp_vec(msg_len + 2); DWORD read_byte = 0; ReadFile(mailslot_handle, &temp_vec[0], msg_len, &read_byte, NULL); temp_vec[msg_len] = 0; temp_vec[msg_len + 1] = 0; const unsigned char * temp_str = &temp_vec[0]; const TCHAR * insert_str = NULL; USES_CONVERSION; #ifdef UNICODE if((*temp_str) == 0x0000) insert_str = A2W(reinterpret_cast<const char*>(temp_str + 2)); else insert_str = reinterpret_cast<const TCHAR *>(temp_str + 2); #else if((*temp_str) == 0xFF && (*(temp_str + 1)) == 0xFF) insert_str = W2A(reinterpret_cast<const wchar_t *>(temp_str + 2)); else insert_str = reinterpret_cast<const TCHAR *>(temp_str + 2); #endif if(IsLastMsg() && _tcscmp(insert_str, _T("goodbye"))) break; else m_log_list.InsertString(-1, insert_str); } } } bool CSnowListWndDlg::IsLastMsg() { return m_last_msg; } void CSnowListWndDlg::SendLastMsg() { HANDLE temp_handle = CreateFile(_T("////.//Mailslot//snowlog"), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(temp_handle != INVALID_HANDLE_VALUE) { TCHAR last_str[] = _T("goodbye"); DWORD write_byte = 0; WriteFile(temp_handle, last_str, sizeof(last_str), &write_byte, NULL); } }
不过在处理宽字符和多字节字符的时候。。。由于考虑到 msglog 函数可能用在很多复杂环境中。。。所以不在msglog
中处理编码了。。。全部交给log窗口处理。。。
为了在log窗口能知道收到字符的编码。。。。所以在每个log字符串的前面忍痛拿两个字节作为标识。。。
程序没怎么测试过。。。。写了个test。。。能用。。。也就将就用着了。。。