![]() |
Platforms, Frameworks & Libraries »
Mobile Development »
General
Beginner
License: The GNU Lesser General Public License
Gynoid: Framework for Mobile DevelopmentBy Vincent_RICHOMMEGynoid is a wrapper around mobile phone APIs (wince, symbian, iPhone) |
C++, C, Win Mobile (WinMobile5, WinMobile6), Mobile (iPhone, Android), Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
Mobile developments are something very exciting because generally it implies to use
all domains of computing. Since you are developing for the end user, you need to create a nice GUI, handle data connections and databases, etc.
The only thing I do not like is the fact that for each platform, you need to learn a new language, new APIs and if you want to port it from one platform to another, you almost always need to write it again.
Big companies like Sun have tried to impose Java to accomplish the sweet dream "Write Once Run Anywhere" but as you already know it didn't succeed and especially in the mobile world.
For politics reasons, Java is not really supported on Windows mobile and iPhone and personally, I don't think managed languages should be used because they are slow, consume more memory, and so on.
The problem is that developers now are used to focus only on the feature they want to implement and they don't want to manage memory anymore. I am not even talking about new developers that don't even know what a pointer is, but that's another problem...
With these considerations in mind, it's been a long time I wanted to write a framework with the following characteristics (lines in italic needs a proof of concept and may change):
So here it is a PRE-ALPHA PREVIEW since I started one month ago but as you will see, we are able to do some simple action with address book.
To finish this introduction, Gynoid name is a human robot designed to look like a human female
and is a joke with Android, the Google's Framework. If you want to tell me that this framework is nonsense and cannot work or this is a lot of work to wrap phone API, I already know it;-)
Actually for this preview, I have only started the Windows CE part and the next step is to do it for iPhone. If it works, I would have proven that it can be done and I will keep on implementing.
To be able to respect all the above criteria, I first studied 3 different platforms and here is what is interesting for Gynoid framework:
Three different platforms and three incompatible SDKs, so the only choice was to wrap API using C language.
So this framework uses C APIs that can be used with static or dynamic linking and for this first publication, I will explain how it works using the address book API.
So let's start with a sample code in plain C:
ErrorCode err = 0;
int iCount = 0;
GDAddrBook* pAddrBook = NULL;
GDAbItem* pAbItem = NULL;
GDPropVal* pPropVal = NULL;
//GDStream* gdStream; // NOT YET IMPLEMENTED
int nCount;
GDArray* gdArray = NULL;
if (!GDAddrBook_Alloc(&pAddrBook) &&
!GDAddrBook_Init(pAddrBook, 0) )
{
if (GDAddrBook_GetCount(pAddrBook, &iCount) == 0)
{
////////////////////////////////////////////////////////////////
// If there is no item in address book we create one
////////////////////////////////////////////////////////////////
if (iCount == 0)
{
if (GDAddrBook_AddItem(pAddrBook, &pAbItem) == 0)
{
err = GDAbItem_SetProperty
(pAbItem, eAbFirstName, _T("Vincent") );
err = GDAbItem_SetProperty
(pAbItem, eAbLastName,_T("emmohcir") );
err = GDAbItem_SetProperty
(pAbItem, eAbMobileTelNumber, _T("0611000000") );
err = GDAbItem_SetProperty(pAbItem,
eAbEmail1Address, _T("v.emmohcir@gynoid.com") );
err = GDAbItem_SetProperty(pAbItem,
eAbEmail2Address, _T("vemmohcir@gynoid.com") );
//GDStream_Init(&gdStream);
//GDAbItem_SetProperty(pAbItem, eAbPicture,
gdStream );
GDObject_Release(pAbItem);
}
}
GDAddrBook_GetCount(pAddrBook, &iCount);
/////////////////////////////////////////////////////////////////
//Now we can retrieve contacts items and their properties
////////////////////////////////////////////////////////////////
for (int i = 0; i < iCount; i++)
{
if (GDAddrBook_GetItem(pAddrBook, i, &pAbItem) == 0)
{
//GDCTSTR lpFirstName = AbCastString
( AbItem_GetProperty(pAbItem, eAbFirstName) );
GDCTSTR lpFirstName = (GDCTSTR)
GDAbItem_GetProperty(pAbItem, eAbFirstName);
GDCTSTR lpLastName = (GDCTSTR)
GDAbItem_GetProperty(pAbItem, eAbLastName);
GDCTSTR lpMobTel = (GDCTSTR)
GDAbItem_GetProperty(pAbItem, eAbMobileTelNumber);
//GDConsole_Writeln(_T
("FirstName %s\nLastName %s\n", ...);
gyn_printf( _T("[%d] %s %s %s\n"),
i, lpFirstName, lpLastName, lpMobTel);
//
//Contact_GetProperty
//(pContact, eContactLastName, &pPropVal);
GDObject_Release(pAbItem);
}
}
}
}
GDObject_Release(pAddrBook);
Even if gynoid is using C interfaces, I have chosen to adopt an oriented approach and API is split in GDAddrBook object and GDAbBitem.
All these GDxxxx objects are actually structures "inheriting" from a GDObject structure declared like this:
typedef struct _GDObject
{
long cRefs;
PFNGDDESTROY pfnDestroy;
} GDObject;
This structure allows to use reference counting to manage object life and once again will simplify object-oriented wrapper. First I started to code gynoid objects using a void as GDObject but to be able to propose a C++ wrapper I needed to use a shared_pointer or that kind of smart pointers that would be able to transfer ownership of underlying gynoid pointers.
I didn't like this solution because I wanted to keep things simple but nothing prevents you from providing different C++ wrappers and I might change my mind and use smart pointers in the future.
Let's keep on discovering gynoid, when using a GDObject you first need to allocate it and then initialize it as show here:
if (!GDAddrBook_Alloc(&pAddrBook) &&
!GDAddrBook_Init(pAddrBook, 0) )
{
...
}
iPhone developers won't be lost and it will remind them of the way they build an object in objective-c 2.0:
Iphone sample code to get address book:
// For people not talking objective-ce the code below is a nested
// construct where alloc message is sent to
// ABPeoplePickerNavigationController and then return object is
// sent a init message
ABPeoplePickerNavigationController *controller =
[[ABPeoplePickerNavigationController alloc] init];
So if we come back to our address book example, we first allocate and init a GDAddrbook "object", then we can start to retrieve associated properties and that's what we do when we call GDAddrBook_GetCount to retrieve the contact number.
One remark is the fact that all getter/setters are done with arguments and not by return code, it will allow a strict error checking.
Once we know how many items we have in the address book, we can start to create an item with some properties by using GDAddrBook_AddItem (that returns a GDAbItem object) and GDAbItem_SetProperty.
Once we have finished adding properties, we only need to release the object by calling the generic function GDObject_Release().
So now you have a global idea of how things work, but I can understand that some developers don't like to code in C especially when designing GUI application and we could benefit from some facilities offered by high level languages.
The easiest object oriented language to use for wrapping is C++ and since memory management is done by our low level C interfaces you will see that, wrappers are nothing more than containers for our GDObject pointers.
Here is the class I have used to wrap GDAbItem pointers:
class AddrBookItem
{
public:
AddrBookItem(): m_gpAbItem(0)
{}
AddrBookItem(const AddrBook& addrBook)
{}
AddrBookItem(GDAbItem* gpAbItem): m_gpAbItem(gpAbItem)
{}
AddrBookItem::AddrBookItem(const AddrBookItem &s) : m_gpAbItem(0)
{
*this = s;
}
AddrBookItem& AddrBookItem::operator =(const AddrBookItem &s)
{
// If we are already holding an item we release it
if (m_gpAbItem != NULL)
{
GDObject_Release(m_gpAbItem);
m_gpAbItem = NULL;
}
m_gpAbItem = s.m_gpAbItem;
GDObject_AddRef(m_gpAbItem);
return *this;
}
virtual AddrBookItem::~AddrBookItem()
{
release();
}
void* getProperty(EAbItemProp eAbitemProp)
{
return GDAbItem_GetProperty(m_gpAbItem, eAbitemProp);
}
ErrorCode setProperty(EAbItemProp eContactProp, GDCTSTR lpPropValue)
{
return GDAbItem_SetProperty
(m_gpAbItem, eContactProp, lpPropValue);
}
ErrorCode show()
{
return GDAbItem_Show(m_gpAbItem);
}
protected:
long release()
{
return GDObject_Release(m_gpAbItem);
}
protected:
GDAbItem* m_gpAbItem;
};
So what if we try to rewrite our first example but this time by using our new C++ wrapper:
////////////////////////////////////////////////////////////////
// Same example done with C++ wrapper
////////////////////////////////////////////////////////////////
using namespace gynoid;
int nCount;
AddrBook addrBook;
iCount = addrBook.getCount();
if (iCount == 0)
{
AddrBookItem abItem = m_addrBook.addItem();
abItem.setProperty(eAbFirstName, _T("Vincent") );
abItem.setProperty(eAbLastName, _T("emmohcir") );
abItem.setProperty(eAbEmail1Address, _T("v.emmohcir@gynoid.com") );
abItem.setProperty(eAbEmail2Address, _T("vemmohcir@gynoid.com") );
}
iCount = addrBook.getCount();
for (int i = 0; i < iCount; i++)
{
AddrBookItem abItem = addrBook.getItem(i);
CString sFirstName = abItem.getProperty(eAbFirstName);
CString sLastName = abItem.getProperty(eAbLastName);
CString sMobTel = abItem.getProperty(eAbMobileTelNumber);
gyn_printf( _T("[%d] %s %s %s\n"),
i, lpFirstName, lpLastName, lpMobTel);
}
So this time as you can see, we have used AddrBook and AddrBookItem objects and we don't even need to handle code deallocation since object destructor does the job for us.
I have used CString object to manage strings but very soon it will be replaced by GDString object.
To finish with object oriented wrappers, there is something that I cannot forget to write about and this is error checking with the questions, exceptions or not exceptions.
Error handling is a difficult question and with gynoid current state, it's a bit early to answer.
But as soon as we start to use an object oriented language, the question about using exceptions is generally not very far. I will try to answer it in the next update of this article.
To illustrate the use of address book API and since I haven't coded the graphical part, I have used WTL and a great touch control made by Windows mobile guru João Paulo Figueira.
In the next article I hope I will be able to use a platform independent GUI (it's already possible to do it using SDL, guichan or efl).
This project is very young and maybe won't go very far, it depends on the next challenge, wrapping address book API from iPhone. Anyway if it doesn't become a multiplatform framework, it will still be useful for Windows CE developers because it simplifies access to native APIs, hides ugly COM interfaces and provides an OO wrapper but only if you need it.
Do not hesitate to contribute and you can follow activity on Sourceforge.
| You must Sign In to use this message board. | |||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 29 May 2009 Editor: Deeksha Shenoy |
Copyright 2009 by Vincent_RICHOMME Everything else Copyright © CodeProject, 1999-2009 Web11 | Advertise on the Code Project |