您的当前位置:首页正文

2409atl,atl3.0到7.0的变化

2024-11-28 来源:个人技术集锦

本文不介绍新的ATL7服务器类和属性.这不是一个完整的列表,只是我目前找到的.

串转换宏一些限制.它从分配内存,可能会在大串时溢出栈.函数退出时,释放该串,而不是在函数引入的域释放.

它使用过时OLE2ANSI定义.如果你查看MSDN上对_alloca(来转换)的注意,它说它在SEHC++EH中使用时有限制.

如,看一下ATL3串转换宏:

USES_CONVERSION;
try
{
      for(int i=0; i< 100000; ++i)
          LPTSTR str = OLE2T(L"Some string string string string string........");
|||//栈溢出,栈上的内存增长...
 //如果上述没有失败,则确保`catch(int)`
      throw int(1); //
}
catch(int)
{
      LPTSTR str = OLE2T(L"Some string string string string string........");
||//`_alloca`不能在`SEH`中使用,否则`EH`生成未处理异常,在`VS.NET`中,`C++`编译时按错误标记
}

ATL7:

串转换宏/类在上述方面有所改进.它对小串使用栈内存,对大串使用堆,因此当栈空间不足时不会溢出栈.串在结束域释放,而不是在函数退出时释放.

可在异常处理器中用.可在循环中使用(因为可由控制).

宏名更易读.形式与以前一样:SourceType2[C]DestinationType.

从:
1,AANSI/WUnicode/Tgeneric到[常数]A,ANSI/W,Unicode/T,generic.
2,CA2T/CA2CT,根据美标定义从美标到通用串_UNICODE
3,CT2A/CT2CA,根据T定义从T通用串ANSI_UNICODE
4,CT2W/CT2CW,从T通用串统一
5,CW2T/CW2CT,根据_UNICODE定义从统一到通用串
6,CT2WEX/CT2CWEX,可指定从T通用统一串和缓冲
7,CW2TEX/CW2CTEX,可指定从统一T的通用串和缓冲
8,CA2W,从美标统一
9,CW2A族,从统一美标
10,CW2AEX/CA2WEX,上述某些typedef/macro使用的实际类.

所以上面代码像这样,不会崩溃:

try
{
     for(int i=0; i< 100000; ++i)
         CW2A str(L"Some string string string string string........");
     throw int(1);
}
catch(int)
{
      CW2A str(L"Some string string string string string........");
}

注意警告.上述所有宏都不能在ATL3代码构造中使用:

LPTSTR str = CW2A(L"some string");

上面代码是错误的.该行后,会析构CW2AEX创建的临时对象.

注意,宏表示C++类,并受域规则控制.
查看问题,请试以下操作:

//使用以2初化串长`大小`,以确保栈大小不够,且对内存用`堆`
LPCTSTR szr = CW2AEX<2>(L"some string");
szr; //在这一行`szr`应该指向`垃圾`

CString:

另一个附加是来操作串的CStringT类.即使此类公开的方法与以前的MFCCString相同.它不是旧的MFCCString.

此类是模板的.它与char,wchar_tTCHAR一起使用的很少.CString是一个:

CStringT< TCHAR, StrTraitATL< TCHAR > > CAtlString;

根据是否使用MFC重定义,这样:

//`#ifdef_AFX`
typedef CAtlString CString;

CStringT自身在MFC/ATL间共享.默认,它使用CRT,但可定义_ATL_MIN_CRT_ATL_CSTRING_NO_CRT来更改CRT.

这反之又使编译器可见相应的,如:

 //使用`CRT`并有更多功能
CStringT< TCHAR, StrTraitATL< TCHAR, ChTraitsCRT< TCHAR > >
or
 //不使用`CRT`,而是使用`win32API`串函数`(wvsprintf,lstrlen,CharNext`等)
 
CStringT< TCHAR, StrTraitATL< TCHAR >, ChTraitsOS<TCHAR> >

另一个CFixedStringT类提供固定的预分配连续缓冲,以优化管理内存.

可通过实现IAtlStringMgr,来自定义管理内存,且已有CAtlStringMgr实现.
它的构造器IAtlMemMgr的指针,IAtlMemMgr可以是预定义的实现,也可是你自己的实现:

1,CCRTHeap,使用CRT
2,CWin32Heap,使用win32
3,CComHeap,使用COM任务分配内存器.
等.如:

CComHeap comHeap;
CAtlStringMgr mg(&comHeap);
CString str(&mg);
str += "some string";

::CoTaskMemAlloc分配内存.

"串和文本类"(MSDN)
"ATL/MFC串转换宏"(MSDN)

集合

ATL7引入了新的集合类.这些类的接口与以前的MFC集合类类似.
这些类是模板类,可传递自己的CElementTraits来处理特例,如CopyElements,RelocateElements,CompareElementsHash.

CAtlArray/CAtlList:

//使用`CStringElementTraits`有效`查找`比较
CAtlArray<CString, CStringElementTraits<CString> > array;

//其他特征包括`CStringRefElementTraits,CStringElementTraitsI`
CAtlList<CString, CStringElementTraits<CString> > list;
list.AddHead(CString("hello"));
list.AddHead(CString("string"));
POSITION pos = list.Find("hello");
if(pos != NULL)
{
    CString str = list.GetAt(pos);
}

CAtlMap

CAtlMap<CString, int, CStringElementTraits<CString> > map;
map.InitHashTable(269);
map["key1"] = 2;
map["key2"] = 2;
int value;
if(map.Lookup("key1", value));

基于红黑树实现CRBTree/CRBMap/CRBMultiMap

CRBMap<int, int> rbMap;
rbMap.SetAt(10, 20);
rbMap.SetAt(30, 40);
CRBMap<int, int>::CPair* p = rbMap.Lookup(30);
//`p->m_key;P->m_value;`
rbMap.RemoveKey(30);

其他各种更特化的类:

CAutoPtrArray/CAutoPtrList/CComUnkArray/CHeapPtrList/CInterfaceArray/CInterfaceList

"集合类"(MSDN)

线程

CWorkerThread<Win32ThreadTraits|CRTThreadTraits>:

简单示例:

class WorkerClass : public IWorkerThreadClient
{
    HANDLE m_hEvent;
    CWorkerThread<Win32ThreadTraits> m_thread;
public:
WorkerClass()
    {
        m_thread.Initialize();
        m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        m_thread.AddHandle(m_hEvent, this, NULL);
    }
    ~WorkerClass()
    {
        m_thread.RemoveHandle(m_hEvent);
        m_thread.Shutdown();
    }
    void ResumeThread()
    {
        ::SetEvent(m_hEvent);
    }
    void FreezeThread()
    {
        ::ResetEvent(m_hEvent);
    }
private:
 //`IWorkerThreadClient`
    HRESULT Execute(DWORD_PTR dwParam, HANDLE hObject)
    {
        FreezeThread();
        return S_OK;
    }
    HRESULT CloseHandle(HANDLE hHandle)
    {
        ::CloseHandle(hHandle);
        return S_OK;
    }
};
Then:
{
    WorkerClass work;
    work.ResumeThread();
    Sleep(5000);
    work.ResumeThread();
    Sleep(5000);
}

下面是CThreadPool的理想用法:

struct IDoSomeWork
{
    virtual void Work()=0;
};
class Work1 : public IDoSomeWork
{
    void Work(){}
};
class Work2 : public IDoSomeWork
{
    void Work(){}
};
class ThreadPoolWorker
{
    public:
//支持`CThreadPoolWorker`原型
    typedef IDoSomeWork* RequestType;
    BOOL Initialize(void* pvWorkerParam)
    {
        return TRUE;
    }
    void Execute(RequestType request, void* pvWorkerParam,OVERLAPPED* pOverlapped)
    {
        request->Work();
    }
    void Terminate(void* pvWorkerParam)
    {
    }
};
{
    CThreadPool<ThreadPoolWorker> pool;
    pool.Initialize();
//
IDoSomeWork* pWork1=new Work1();
pool.QueueRequest(pWork1);
//
IDoSomeWork* pWork2=new Work2();
pool.QueueRequest(pWork2);
//
    Sleep(5000);
    delete pWork1; delete pWork2;
}

管理内存

CHeapPtr<CComAllocator | CCRTAllocator>:
CHeapPtr<int, CComAllocator> ptr;
ptr.Allocate(100);
 //该类不适合对象数组,因为它不调用`delete[]`,而只调用`删`.
CAutoPtr<CString> ptr(new CString("string"));
CAutoVectorPtr<CString> pVec(new CString[100]); //这会调用`delete[]`

CComGITPtr中:

管理GIT表中的指针.创建GIT并调用IGlobalInterfaceTable方法.

其他更特化的类包括:
1,CAutoPtrArray
2,CAutoPtrList
3,CComHeap
4,CComHeapPtr
5,CComPtrBase
6,CCRTAllocator
7,CCRTHeap
8,CGlobalHeap
9,CHandle
10,CHeapPtrBase
11,CHeapPtrList
12,CLocalHeap
13,CWin32Heap

管理内存类(MSDN)

文件

1,CAtlFilewin32API的文件精简包装器.CreateFile,ReadFile,WriteFile等.
2,CAtlTemporaryFile可用于临时文件.会自动命名,打开,关闭和删除它们.
3,CAtlFileMappingBase/CAtlFileMapping可用来映射文件:

CAtlTemporaryFile file;
CAtlFileMapping<char> filemap;
file.Create(NULL, GENERIC_READ|GENERIC_WRITE);
file.SetSize(1024);
filemap.MapFile(file, 1024, 0, PAGE_READWRITE, FILE_MAP_READ|FILE_MAP_WRITE);
char* pMem = filemap;
strcpy(pMem, "hello");

安全

ATL7包括win32API安全性的包装器.
快速示例:

CSid sidDenied;
sidDenied.LoadAccount("Leo");
CDacl dacl;
//试`拒绝`或`允许`并查看`OpenEvent`稍后的行为
dacl.AddDeniedAce(sidDenied, GENERIC_ALL);
//dacl.AddAllowedAce(sidDenied,GENERIC_ALL);
CSecurityDesc desc;
desc.SetDacl(dacl);
CSecurityAttributes secattr(desc);
//限制`命名事件的权限`
CHandle hEvent(CreateEvent(&secattr, FALSE, FALSE, "NamedEvent"));
//试用所有访问权限打开它
CHandle hEventOpen(OpenEvent(EVENT_ALL_ACCESS, FALSE, "NamedEvent"));
//如果在上面添加了`拒绝`,它应该会失败.如果添加了`允许`,则应会成功

if(GetLastError() == ERROR_ACCESS_DENIED)
    ATLTRACE("\n\nAccess denied when opening event\n\n");
CSecurityDesc descCheck;
AtlGetSecurityDescriptor("NamedEvent",SE_KERNEL_OBJECT, &descCheck);
CDacl daclCheck;
descCheck.GetDacl(&daclCheck);
CSid::CSidArray sidarr;
daclCheck.GetAclEntries(&sidarr);
for(UINT i=0; i<sidarr.GetCount(); ++i)
{
    ATLTRACE("%s\n", (LPCTSTR)sidarr[i].Sid());
    ATLTRACE("%s\n", (LPCTSTR)sidarr[i].AccountName());
    ATLTRACE("%s\n", (LPCTSTR)sidarr[i].Domain());
}

杂项

#import现在可取progid/libid而不仅是硬编码文件名.如:

#import <libid:20000000C-500A-100BB005-000000000000> version("2.2")
#import "progid:SomeServer.哈哈.1" embedded_idl, no_namespace

1,按如:CAtlComModule/CAtlWinModule/CAtlDllModuleT/CAtlExeModuleT/CAtlServiceModuleT/等其他类替换CComModule.
2,不再显式调用Init()/Term().这些方法现在由模块类的相应ctor/dtor调用.
3,不再需要BEGIN_OBJECT_MAP/END_OBJECT_MAP.改用全局域内的OBJECT_ENTRY_AUTO.
4,并在链接自动生成ATL对象映射中.它使用链接器段声明把所有全局的映射项收集到一个列表中.

CComCurrency,CURRENCY类型的包装器
CAtlException,定义与ATL相关的异常

CImage,根据GDI+.可用jpeg,gif,bmp,png.见"早期系统的CImage限制"(MSDN)
_U_STRINGorID/_U_MENUorID/_U_RECT/CPoint/CRect/CSize,各种简单的包装器.见"工具类"(MSDN)
atlsync.h中定义的同步包装器:CCriticalSection,CEvent,CMutexCSemaphore.但在MSDN没有记录它们.

显示全文