segunda-feira, 8 de outubro de 2007

Recuperando um ponteiro para class Document

Muitas vezes quando utilizamos o padrão Model-View-Controller (que espero falar aqui no futuro) , precisamos acessar dados contidos na nossa classe Document.

Para fazer isto precisamos de um ponteiro que aponte para o objeto desta classe. Podemos recuperar esta referência através de um método da classe CEikAppUi chamado Document(). Este método retorna um ponteiro genérico do tipo CEikDocument. Para poder utilizar os métodos da nossa classe document precisaremos da um cast da classe base CEikDocument para a nossa classe CMeuDocumento (por exemplo).

Para ilustrar melhor a relação entre as classes aqui está um diagrama de classes. Para a nossa classe Document temos:

Não está explicíto, mas por estas classes começarem com a letra C, sabemos que são derivadas de CBase.

Recuperando a referência da nossa classe Document dentro de AppUi

Classes AppUi são em geral derivadas de CAknAppUi (caso não implemente views) ou CAknViewAppUi (caso a aplicação trabalhe com views). Na relação de hierarquia elas herdam o método Document() de CEikAppUi. Considerando que você precise do ponteiro para Document dentro de sua classe AppUi, basta apenas chamar o método Document(), dando o devido cast.



Exemplo:

// Cast para da classe base para a classe filho.
CMeuDocumento* documento = static_cast(Document());
// Chamando um método qualquer.
documento->MinhaFuncao();
Recuperando a referência para a nossa classe document dentro do container

Classes derivadas de CCoeControl possuem um atributo membro iCoeEnv, que é um ponteiro do tipo CCoeEnv. Esta classe possui um método AppUi() que retorna um ponteiro do tipo CCoeAppUi, iremos utilizar este ponteiro para chamar o método Document() de CEikAppUi. Como vemos no diagrama de classes ao lado, CCoeAppUi não possui o método Document() implementado (ele está implementado em CEikAppUi , filha de CCoeAppUi), tereremos então quer dar um cast para a classe AppUi de nossa aplicação para poder acessar este método.

Exemplo:
// Conversão do tipo CCoeAppUi para CMeuAppUi.
CMeuAppUi* appUi = static_cast(iCoeEnv->AppUi());
// Conversão do tipo CEikDocument para CMeuDocumento.
CMeuDocumento* documento = static_cast(appUi->Document());
// Chamando um método qualquer.
documento->MinhaFuncao();
Referências

Developing Series 60 Applications: A Guide for Symbian OS C++ Developers (cap. 4)

quarta-feira, 3 de outubro de 2007

Utilizando classes Singleton no SymbianOS

Sigleton é um padrão de projeto definido no Livro Design Patterns: Elements of Reusable Object-Oriented Software. Este padrão diz que para uma determinada classe apenas uma única instância deve existir por todo o programa.

Em C++ padrão a forma mais simples de se criar uma classe Singleton é utilizar um ponteiro estático e um método estático. Em SymbianOS isto funciona para EXE mas não para DLL*. Pois este ponteiro estático é considerado como um
Writable Static Data (variável global que existe durante toda a vida do processo), e isto não é permitido para DLLs.

Para fazer a criação de singletons temos duas possibilidades, utilizar a classe base CCoeStatic , ou utilizar Thread Local Storage (TLS). Até o momento nunca utilizei TLS então irei focar na utilização da classe CCoeStatic. A principal desvantagem na utilização de CCoeStatic é que você não pode utiliza-lo em aplicações baseadas em console (sem User Interface).

A lógica utilizada será bem parecida com o singleton em C++ padrão, a diferença é que não iremos utilizar um ponteiro estático. Iremos precisar criar um UID único para a classe (único dentro da aplicação), ele será utilizado para identificar de qual classe iremos obter a instância, caso esteja trabalhando com várias classes Singleton.

Arquivo: ExemploSingleton.h

/*
* Exemplo de criação de classes Singleton utilizando CCoeStatic.
* Autor: Leonardo Soares e Silva
*/

#include // Cabeçalho de CCoeStatic.

class CExemploSingleton : public CCoeStatic
{
public:
/* Retorna uma instância desta classe.
* Na primeira vez que este método for chamado ele fará a criação da instância.
* Em chamadas subsequentes será retornada esta instância.
*/
static CExemploSingleton* InstanceL();
~CExemploSingleton();
private:
/* Construtor precisa ser privado para evitar que outras classes a instancie diretamente.*/
CExemploSingleton();
/* Construtor de segunda-fase caso precise realizar alguma operação que possa abandonar */
void ConstructL();
};

Arquivo: ExemploSingleton.cpp

#include "ExemploSingleton.h"

/* UID definido para a classe CExemploSingleton.
* Este UID precisa ser único para esta classe dentro da aplicação.
*/
const TUid KUidClasseSingleton = { 1 };

/* Construção da classe.
* Passamos para CCoeStatic a UID da classe e prioridade de destruição da instância.
*/
CExemploSingleton::CExemploSingleton() : CCoeStatic( KUidClasseSingleton, EDefaultDestructionPriority )
{

}

CExemploSingleton::~CExemploSingleton()
{
// Não implementado.
}

CExemploSingleton* CExemploSingleton::InstanceL()
{
CExemploSingleton* instancia = static_cast
( CCoeEnv::Static( KUidClasseSingleton ) );
/* Somente entrará neste if na primeira chamada a InstanceL();
* Chamadas subsequentes a este método retornarâo esta instância.
*/
if( !instancia )
{
instancia = new (ELeave) CExemploSingleton();
/* Adiciona o ponteiro ao CleanupStack para garatir que está referência não será perdida caso ConstructL abandone.*/
CleanupStack::PushL( instancia );
/* Chamada ao construtor de segunda-fase */
instacia->ConstructL();
/* Após chamar métodos que possam abandonar , liberar da pilha */
CleanupStack::Pop( instancia );
}

return instancia;
}

void CExemploSingleton::ConstructL();
{
// Não implementado
}

O código por si só é bastante fácil de compreender. Como disse anteriormente basta fazer chamadas ao método InstanceL() para receber a referência da classe Singleton. Na primeira chamada será alocado o ponteiro e nas outras será apenas retornado a instância. Algo que vale ressaltar é a construção da classe:

CExemploSingleton::CExemploSingleton() : CCoeStatic( KUidClasseSingleton, EDefaultDestructionPriority )
{

}

Passamos através do contrutor para CCoeStatic dois argumentos. Uma das definições do construtor de CCoeStatic é:

CCoeStatic(TUid aUid, TInt aDestructionPriority, TScope aScope=EThread);

Onde:

aUid = Uid da classe singleton.
aDestructionPriority = Define com que prioridade a instância será destruída. Quanto maior este valor , mais cedo o objeto será destruído. Valores positivos fazem com que o objeto seja destruído antes de CCoeAppUi enquanto valores negativos fazem com que o objeto seja destruído após CCoeAppUi.
aScope = Define para quem o objeto estará acessível. Por definição é para o Thread da aplicação.

---
* = A partir da versão 8.1 passou a ser suportado.

sábado, 4 de agosto de 2007

Tipos básicos em Symbian

Opa, antes de começar a falar sobre tipos de variáveis em SymbianOS preciso explicar o porquê estou ausente do blog. Primeiro por que estava de férias e no tempo livre estava engajado em um projeto pessoal de desenvolvimento de um pequeno jogo clone do snake da Nokia (concluído, depois posto o source, funciona legal no emulador mas não funcionou no meu N95 e não tive tempo de verificar o porquê até por que não poderei depura-lo on-device já que minha versão do Carbide é a express), segundo que com as aulas começando e com retorno do projeto fiquei sem tempo de postar mas vou tentar sempre que possível postar algo interessante aqui.

Ok, vamos ao que interessa...

Se você não conhece os tipos básicos utilizados em SymbianOS considere a leitura do artigo Tipos Básicos no Nokia Wiki. Estas mudanças TInt, TUint, TReal, etc são apenas typedefs dos tipos padrões de C/C++ mas devem ser utilizados pois é assim que o compilador irá interpretá-los. O que gostaria de dizer neste post se refere mais a eficiência na programação.

Tipos Inteiros

Sintaxe:

typedef signed int TInt;

O SymbianOS permite que programadores utilizem tipos inteiros de 8, 16, 32 ou 64 bits, porém segundo o próprio site www.symbian.com é recomendável a utilização do tipo TInt sempre que possível. Isto pode ser explicado por motivos simples, o SymbianOS trabalha em cima da arquitetura ARM e nessa arquitetura o tamanho da palavra é de 32bits. Quando você utiliza inteiros (TInt16 e TInt32) com tamanho menor que esta palavra ela terá que ser então "modificada" para o tamanho da palavra que a arquitetura utiliza

Nota: TInt8 na verdade é um typedef do tipo char e TInt32 é um typedef do tipo long int.

Por isso a utilização de inteiros com tamanhos definidos deve ser utilizada quando a precisão no tamanho dos dados é necessária, em outros casos aconselha-se utilizar TInt.

Tipos flutuantes

O uso de tipos flutuantes deve ser evitado sempre que possível pois a maioria dos dispositivos em que o SymbianOS trabalha não dá suporte a operações de ponto flutuantes em hardware, ficando assim sua performance comprometida seriamente.

segunda-feira, 2 de julho de 2007

Gerência de memória e recursos

Bem, seria meio redundante eu postar os mesmos artigos que já postei na Nokia Wiki aqui. Então para evitar isto e para criar o costume de se utilizar a Wiki resolvi fazer algumas referências aqui a artigos encontrados lá. Como o sistema de busca dele não é um dos melhores às vezes você não encontra tudo que procura, talvez isso possa ajudar.

O post de hoje será em relação a gerência de memória e recursos. Quando se programa para um dispositivo que possui tantos recursos limitados como um celular é preciso ter cuidado para não disperdiçar nada. A um tempo atrás os celulares eram reduzidos apenas a capacidade de realizar e receber chamadas. Hoje celulares como o N93, N95, N800 apresentam recursos como aceleração 3D e processadores mais robustos como o ARM11 que opera a 300MHZ mas mesmo assim ainda são muito limitados.

Começando por este artigo onde é arbodado os conceitos básicos de stack , heap, exceções (abandonos ou leaves em Symbian), pilha de limpeza entre outros. Gostaria de dar ênfase para a construção em duas fases e para pilha de limpeza.

Pilha de limpeza e Construção em duas fases são melhores abordados nesses links.

Para finalizar, algumas regras na gestão de recursos que procuram minimizar estes desperdícios podem ser encontras neste link

domingo, 1 de julho de 2007

Códigos de erros

Ao ocorrer um erro durante a execução de uma aplicação é exibido o porquê deste erro ter acontecido. Podemos chamar isto de "Códigos de erros" e conhecê-los é importante para solucioná-los. Escrevi este artigo para o Nokia Wiki PT comentando sobre cada um dos erros e como corrigí-los e apesar de ainda incompleto cobre os erros mais comuns, caso conheça mais erros não esqueça de contribuir! ;)

Link para o artigo aqui!

Caso queira verificar a lista completa de erros ela pode ser encontrada na documentação do SDK do Symbian, link aqui!

segunda-feira, 25 de junho de 2007

Iniciando o desenvolvimento de aplicações para Symbian.

Este artigo: Començando a programar para dispositivos móveis resume de forma clara e objetiva como iniciar o desenvolvimento de aplicações para Symbian. Não apenas fazendo a introdução nas possibilidades de programação para Symbian mas aborda quais são os conhecimentos necessários para isso, dando uma visão geral desde lógica de programação até os passos necessários para "meter a mão na massa". São referenciado também alguns cursos de universidades sobre estes temas e também contem uma seção que fala sobre alguns materiais para leitura, como sites, livros, forums, etc.

Com certeza uma boa pedida!

quarta-feira, 20 de junho de 2007

Trabalhando com Bitmaps

Esse foi um dos meus maiores problemas quando comecei a programar em Symbian. Como usar bitmaps em minhas aplicações?! A falta de material didático dificulta para qualquer pessoa mas nada que um pouco de leitura e pesquisa não resolva.

O SymbianOS não utiliza o formato nativo de Bitmaps por questões de recursos, é preciso convertê-los para multibitmaps (.mbm). Até onde sei existem duas formas de realizar a conversão, uma é através do arquivo de projeto (.mmp) e a outra é utilizando um aplicativo que vem com o Kit SDK do Symbian chamado de bmconv. Ao converter um bitmap são gerado dois arquivos, o .mbm e um .mbg, nesse .mbg fica a enumeração com os IDs das imagens, escrevi mais detalhadamente sobre como realizar essa conversão no wiki da nokia e você pode ler aqui!. Não entrarei em detalhes aqui pois todas essas informações estão na wiki!

Para utilizar bitmaps é preciso criar uma instância da classe CFbsBitmaps e carregar o bitmap. Mais informações sobre essa classe podem ser encontradas aqui!
PS: é preciso incluir o cabeçalho fbs.h, linkar a biblioteca fbscli.lib e incluir o arquivo .mbg referente aos bitmaps.

Após criar uma instância CFbsBitmap é preciso alocar memória para ela e então carregar a imagem, isto pode ser feito no ConstructL() do AppView da aplicação. ex.:

//alocando memória utilizando o operador new sobrecarregado
iBitmap = new (ELeave) CFbsBitmap;
iBitmap->Load(_L("\\Apps\\imagem.mbm"), EMbmImagemTeste);

Dentro da função Draw iremos usar a função BitBlt(const TPoint &aPos, const CFbsBitmap *aDevice) da classe CWindowGc para exibir a imagem para o usuário ex.:

//exibe o bitmap na origem
gc.BitBlt(TPoint(0,0), iBitmap);

Você pode também utilizar a função DrawBitmap que associa o bitmap a um retângulo. ex.:

TRect retangulo(Tsize(40,40), TPoint(0,0);
gc.DrawBitmap(retangulo, iBitmap);

Pronto, procurei ser o mais objetivo possível por que isso não é difícil, meu principal problema foi a ocorrência de erros por não ter linkado a bilioteca fbscli.lib (na versão 1.1 do Carbide era um pouco mais complicado), mas fora isso não tive problemas. Você pode encontrar um exemplo pronto na wiki da nokia. Link aqui!

segunda-feira, 18 de junho de 2007

Gerando números aleatórios

Ontem estava programando e tive a necessidade de gerar uma sequência de números aleatórios. Logo pensei no srand ou então em criar minha própria função para isso. Para não re-inventar a roda resolvi dar uma pesquisada sobre a existência da função rand para Symbian e a encontrei na biblioteca de funções matemáticas E32Math.h (inclusive vale a pena checar o documento sobre as funções dessa biblioteca Link aqui!), de fato encontrei outra função rand, na verdade as dos padrões C , mas preferi fazer uso da biblioteca matemática.

Para quem já utilizou essa função no C/C++ sabe que a melhor forma de se gerar um número aleatório é baseado na hora do sistema, em Symbian não será diferente. Iremos utilizar a classe TTime para pegar a hora do sistema, essa hora será convertida para um inteiro64 e então passada como argumento na função Math::Rand(TInt64& aSeed); Para gerar vários números aleatórios basta fazer várias chamadas a essa função e passando como argumento sempre o mesmo Seed. Você não deve mudar isto! Vamos ao exemplo:

== MinhaApliacacaoAppView.h ==
class CMinhaAplicacaoAppView : public CCoeControl
{
private:
//inteiro que será utilizado para gerar os números aleatórios
TInt64 iSeed;
public:
TInt GerarNumeroAleatorio();
};

== MinhaApliacacaoAppView.cpp==
#include "MinhaApliacacaoAppView.h"
#include E32Math.h //(OBS: adicione < > entre E32Math.h , o blog não me permite fazer isto)


void CMinhaApliacaoAppView::ConstructL()
{
//instancia da classe TTime
TTime tempo;
//Recebendo a hora do sistema
tempo.HomeTime();
//Convertendo para inteiro
iSeed = tempo.Int64();
}

TInt CMinhaApliacacaoAppView::GerarNumeroAleatorio()
{
//Gerando número aleatorio de 0 à 100

TInt numeroAleatorio = Math::Rand(iSeed)%101;
return numeroAleatorio;
}
Ehhhhhh, ok está sem identação mas é que não existe um padrão para postar código de programação aqui! (pelo menos não que eu conheça)

domingo, 10 de junho de 2007

Possibilidades de desenvolvimento para Symbian

Do C++ ao Flashlite, passando por Lua, Perl, Python, JavaME entre outros. Essas são as possibilidades de desenvolvimento para Symbian*. Cada uma com suas vantagens, Python e FlashLite vem ganhando um espaço cada vez maior principalmente do JavaMe. Por sua popularidade o FlashLite (que realmente aplica o conceito de "Write once, run anywhere") promete ganhar cada vez mais espaço nesse mercado de dispositivos móveis. Seja por sua facilidade de programação, grande quantidade de APIS prontas ou pelo número crescente de programadores. Python também se apresenta como uma alternativa robusta, com acesso a diversos dispositivos do celular como bluetooth, infra-vermelho, câmera etc, e ainda com a vantagem de poder se programar direto no celular. No outro extremo encontramos o Symbian C/C++ que sem dúvidas é a linguagem mais poderosa atualmente, possui acesso a vários (praticamente todos) os dispositivos do celular, diversas APIs já prontas, sem contar que seu desempenho é bastante superior se comparado ao JavaME. Apesar de ser mais complexa que as outras suas vantagens superam estes problemas.

Mas então qual linguagen utilizar? Como em qualquer sistema operacional isto depende das necessidades do projeto, para jogos menos complexos eu iria de FlashLite, pela sua portabilidade e pela sua facilidade de desenvolvimento. Para aplicações mais robustas eu iria de Pyhton ou Symbian C/C++. Na minha opnião depende também qual público alvo deseja-se atingir, não podemos esquecer que praticamente todos os aparelhos móveis (de smartphones a celulares mais simples) rodam aplicações Java. Então como disse anteriormente, tudo depende das necessidades do projeto.

* - Depende da versão do Symbian, por exemplo, lua está dispônivel apenas a partir da S60 2º edição.

sexta-feira, 8 de junho de 2007

Desenvolvendo para Symbian C++

O Symbian C++ foi baseado nos padrões C/C++, porém foram feitas algumas mudanças para optmizar o código para um dispostivo com recursos limitados como o smartphone. Algumas mudanças podem ser encontradas nos tipos das variáveis, forma na qual as exceções são tratadas entre outras. Criarei em breve um post para tratar com mais calma sobre assunto. O desenvolvimento de aplicações para Symbian C++ pode ser feito no Carbide C++, MetroWerks CodeWarrior ou Visual Studio .NET. Irei entrar em detalhes apenas sobe o Carbide C++ por ser uma IDE gratuíta.

Carbide C++: Foi desenvolvido pela Nokia e baseado no Eclipse , ofecere uma IDE e compilador necessários para o desenvolvimento de aplicações em Symbian C++. Sua versão express é gratuíta e suficiente para estudos e/ou desenvolvimento de aplicações menores.

Downloads necessários: Carbide C++ 1.2 , Active Perl5.6 (Precisa ser o 5.6, outras versões podem não funcionar), SDK para desenvolvimento (faça o download da SDK referente a qual plataforma você vai desenvolver, s603rd , s602nd ou s601st).

Atenção: Se você usa WindowsXP é aconselhável que se instale o SP2.
Atenção 2: Não consegui rodar o emulador do carbide antes de instalar o drive da minha Geforce, o drive padrão do windows não funcionou. Caso seu emulador abra e feche logo em seguida talvez seja peciso atualizar o drive da sua placa de vídeo para o drive original.

1) Passo - Faça a instalação do Active Perl, use o diretório padrão.
2) Passo - Instale a SDK (lembre-se o diretório não pode conter espaços, utilize _ ao invés).
3) Passo - Instale o Carbide C++. Após instalar basta ir em File->New->Projetct... , escolha Symbian Os e então escolha qual template você vai programar.

quarta-feira, 6 de junho de 2007

May contributions contest e Wiki Contributor of the Month


A Nokia valoriza muito aquelas pessoas que procuram ajudar novos desenvolvedores. Seja no Forum ou no Nokia-Wiki, e durante o mês de maio realizou uma competição para escolher cinco pessoas que mais contriburiram para o crescimento do Wiki, seja com artigos, exemplos de códigos, "how-to" , etc. Os vencedores ganhariam nada mais nada menos que um smartphone N95 (Para quem não conhece, este é o mais novo lançamento da Nokia, e contêm funções como GPS, VoIP, WI-FI, Câmera 5MP entre outras muitas funções), para minha surpresa, ontem recebi a notícia que fui um dos escolhidos assim como também ganhei o prêmio de Wiki Contributor of the month, que premia aqueles que contribuiram para o cresimento da Wiki durante o mês. Fiquei muito surpreso, a algum tempo atrás havia resolvido criar e traduzir alguns artigos para o português, o objetivo principal era de criar conteúdo em português para Symbian (já que não existe), então a medida que ia me aprofundando nos meus estudos eu ia criando artigos (isso também me ajudou pois fixava o conteúdo). Juntamente com a notícia do prêmio, tive a felicidade de ver o lançamento da versão Português do Nokia-Wiki , por esses reconhecimentos fui indicado para o Forum Nokia Champions que destaca os desenvolvedores por suas contribuições, assim como uma série de outros bônus.

Até o momento a wiki conta com 39 artigos, indo do básico até o intermediário, conta com artigos desde como instalar o kit de desenvolvimento para S603rd até gerência de logs. Espero que esses artigos sejam úteis e ajudem novos desenvolvedores, procurei focar pontos onde tive os maiores problemas ou que eram de mais difícil aprendizado. Não se esqueçam de fazer as suas contribuições, pois a base de tudo é a cooperatividade.

Primeira mensagem.

Como primeira mensagem, vou falar um pouco sobre os motivos para a criação deste blog. A comunidade de desenvolvedores para Series60 no Brasil é mínima assim como o conteúdo em português (smartphone não é tão popular como em países da europa, asia e américa do norte), então resolvi dar minha contribuição. Pensei primeiramente em criar um portal com um forum em portuguÊs mas recebi a notícia de que o Forum da nokia em breve lançará uma seção para desenvolvedores que falam português, então resolvi criar este blog para postar novidades sobre S60 assim como algumas dicas/tutoriais a medidada que eu for me aprofundando nos estudos. Atualmente estou fazendo parte de um grupo de pesquisa na minha faculdade relacioado ao desenvolvimento e pesquisa de aplicativos para dispositivos móveis, mais precisamente para SmartPhones utilizando Symbian C++. Orientados pela professora Cledja Rolim (Cefet-Al)