logo
Contato | Sobre...        
rebarba rebarba

Rodrigo Strauss :: Blog

follow us in feedly

C++ com sanidade: usando ATL em aplicações

Muita gente costuma dizer que em C++ programa-se muito para pouco resultado. Todo mundo assume que esse "resultado" roda bem mais rápido, mas já é outra coisa... Eu acredito que é possível manter a sanidade e a vida social programando em C++, só é preciso ter um pouco mais de conhecimento e um pouco mais de cuidado. Pretendo escrever bastante sobre isso se eu tiver tempo.

A lenda sobre o fato de programar em C++ ser trabalhoso, vem principalmente do fato de que as pessoas usam C++ como um C melhorado. Conheço vários programadores C++ que não usam STL e que ainda ficam manipulando char* a toda hora, em pleno ano de 2005 (eu fazia isso até o ano passado). Apesar do C++ ser um superset da linguagem C, ele tem dezenas de melhorias que permitem escrever um código mais organizado, simples e conciso.

Eu tenho estudado muito sobre qualidade de código, incluindo sobre como escrever um código claro e com menos bugs. Quanto mais eu estudo, mais eu vejo como isso é possível, e como C++ é uma ferramenta maravilhosa para esse fim. C++ segue o conceito usado para aproximar uma linguagem do nível ideal: fazer as coisas simples serem simples, e as coisas complexas serem possíveis. Muitas linguagens de alto nível que existem fazem o simples ser simples, mas fazem o complexo ser complicado demais e cheio de gambiarras e interops.

A API Win32 não é lá muito sã. Para criar uma janela em Win32 puro (como Petzold), é necessário uma centena de linhas de código. E tudo que você ganha é uma janela branca e muito feia. Mas não podemos esquecer que a API Win32 ainda herda da API do Windows 1.0, que foi feita para linguagem C, usando os conceitos de programação da época. O mais engraçado é que ainda usam esse conceito hoje em dia... Alguém já tentou enviar uma mensagem para o MSMQ usando a API para C? É coisa para quem não tem mais o que fazer. Apesar de gostar bastante de Win32, eu assumo que é um pouco por masoquismo e por orgulho de ter conseguido aprender isso... :-)

Escolhi ATL para começar esse assunto porque, além de ser uma biblioteca que eu gosto muito, ela ajuda a trazer um pouco de sanidade à programação Win32. E ao contrário da MFC, não é um framework que você é obrigado a seguir. MFC é bom e tem seu espaço, mas vou explorar a ATL porque ela permite o uso "avulso" e por ser menos usada em Win32.

ATL (Active Templte Library) é basicamente uma biblioteca de templates usada para facilitar o desenvolvimento de componentes COM. Além de cumprir de modo soberbo esse papel, ela também tem diversas classes (muitas delas desconhecidas) para facilitar a programação Win32, tornando nossa vida muito mais fácil. A ATL, ao contrário do MFC, não cria dependência de nenhuma DLL. É só incluir os headers e sair usando. Se você fizer um disassembly de um executável RELEASE que usa ATL, verá que ela é um "thin layer", e que muito da ATL "desaparece" (vira inline) depois da otimização.

Hoje vamos ver um exemplo de uso da ATL para leitura de arquivos e para buffers:


#define UNICODE
#define _UNICODE

#include <atlbase.h>
#include <atlstr.h>
#include <atlfile.h>
#include <atlmem.h>

int wmain(int argc, WCHAR* argv[])
{
   HRESULT hr;
   ATL::CAtlFile hFile;
   ATL::CString strFileName;
   ATL::CHeapPtr<char> pBuffer;
   unsigned __int64 iSize;
   
   strFileName = L"c:\\boot.ini";

   //
   // abrindo o arquivo. Bem parecido com o ::CreateFile, mas com parâmetros defaults
   //
   hr = hFile.Create(strFileName, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING);

   if(FAILED(hr))
   {
      MessageBox(NULL, ATL::CString("Erro ao abrir ") + strFileName, L"Erro", MB_ICONERROR);
      return hr;
   }

   hFile.GetSize(iSize);

   //
   // usando o CHeapPtr como buffer. Vamos alocar, e ele desaloca no destrutor
   //
   pBuffer.Allocate(iSize + 1);

   //
   // vamos ler o conteúdo do arquivo, usando o CHeapBuffer
   // Como ele sobrecarrega os operadores de conversão, podemos usá-lo
   // como se fosse mesmo um ponteiro para um buffer
   //
   hFile.Read(pBuffer, iSize);

   //
   // Vamos colocar um \0 no final para fechar a string
   //
   pBuffer[iSize] = '\0';
   
   //
   // vamos usar MessageBoxA (ANSI) pq nosso programa é UNICODE
   // Não se esqueça que os arquivos texto geralmente são ANSI
   //
   MessageBoxA(NULL, pBuffer, "Conteúdo do arquivo", MB_OK);


   //
   // Não precisamos desalocar o buffer
   // não precisamos fechar o handle do arquivo
   //
   
   return 0;
}

Note que o código usa UNICODE, já que não temos necessidade de suportar Windows 9x nesse exemplo. Note que esse código é mais claro do que o código que usa Win32 diretamente, e com mais facilidades. Não precisamos fechar o HANDLE para o arquivo e não precisamos desalocar o buffer usado. Eu costumo usar o "ATL::" para ser notório quais objetos são da ATL. Isso evita confusão com o objetos parecidos que existem na MFC.


Em 24/03/2005 03:50, por Rodrigo Strauss


  
 
 
Comentários
Algo a dizer?
Nome:


Site:


E-mail:


Escreva o número vinte e seis:


 Não mostre meu e-mail no site, não serve pra nada mesmo...

Comentário





Os comentários devem ser sobre assuntos relativos ao post, eu provavelmente apagarei comentários totalmente offtopic. Se quiser me enviar uma mensagem, use o formulário de contato. E não esqueça: isso é um site pessoal e eu me reservo o direito de apagar qualquer comentário ofensivo ou inapropriado.
rebarba rebarba
  ::::