posted by Jean-Louis Villecroze on Wed 8th Dec 2004 21:40 UTC

"Zinzala, Page 5/11"
Skin as shared object

Now that we have all our graphics neatly packed away in a C++ file, it is time to see how we are going to integrate it into to a shared object. To help us load a shared object later on, we will be using the class cAddOn, provided by the Zinzala SDK. This class is a simple wrapper around the famous function dlopen().

Shared object contents

Each skin shared object must provide a function through which a given resource can be retrieved. A simple tUint16 is enough to identify each resource defined in the C++ file we have created from the graphics:

const tBitmapResource *gResources[] = {
   &kRscBitmapBackground,
   &kRscBitmapDimmed,
   &kRscBitmapNormal,
   &kRscBitmapPressed,
   &kRscBitmapAnimate1,
   &kRscBitmapAnimate2,
   &kRscBitmapAnimate3,
   &kRscBitmapForwardN,
   &kRscBitmapForwardD,
   &kRscBitmapPauseN,
   &kRscBitmapPauseD,
   &kRscBitmapPlayN,
   &kRscBitmapPlayD,
   &kRscBitmapBackwardN,
   &kRscBitmapBackwardD,
   &kRscBitmapStopN,
   &kRscBitmapStopD
};

tUint16 kResourcesCount = 17;

extern "C" const tBitmapResource *GetResource(tUint16 aResourceID)
{
   if(aResourceID < kResourcesCount)
      return gResources[aResourceID];
   else
      return NULL;
}

The array gResources contains a pointer to each graphic resource that we created earlier. The function GetResource() accesses the array and returns a resource from a position in the array.

You may have a look at the skin C++ file. The functions _AddOn_* are mandatory since they are required by the class cAddOn.

Loading the shared object

To load and access the skin shared object, we are now going to derive the class cAddOn and add to it a method that will retrieve the resource when given a resource ID. It will simply use the GetResource() function defined in every skin shared object.

Here's the declaration of the class:

class cDSkin : public cAddOn
{
   public:
      cDSkin(const tChar *aPath);

      const tBitmapResource &GetResourceL(tSkinResource aResource);

   private:
      const tBitmapResource *(*iFunction)(tUint16 aResourceID);
};

The member data iFunction will be set in the constructor to point to the shared object function we implemented earlier. The method GetResourceL() relies on it to get the tBitmapResource associated with the requested resource. Note that if the resource doesn't exist in the skin, this method will throw an exception. This is implied by the L, as in Leave, that is added to the end of its name. This is a common practice in Symbian. This naming convention allows developers to easily recognize which methods can throw an exception.

The type tSkinResource defines all the resources that should be accessible from any skin:

enum tSkinResource {
   eResBackground = 0,
   eResDimmed,
   eResNormal,
   eResPressed,
   eResAnimate1,
   eResAnimate2,
   eResAnimate3,
   eResForwardN,
   eResForwardD,
   eResPauseN,
   eResPauseD,
   eResPlayN,
   eResPlayD,
   eResBackwardN,
   eResBackwardD,
   eResStopN,
   eResStopD
};

Here's the code of the class constructor:

cDSkin::cDSkin(const tChar *aPath)
   : cAddOn(aPath)
{
   if(!iFault)
   {
      iFunction = (const tBitmapResource *(*)(tUint16 aResourceID))Find("GetResource");
      if(!iFunction)
         iFault = kErrNotFound;
   }
}

If the skin shared object is correctly loaded, the data member iFault will be kErrNone (whose value is 0). We can then use the method cAddOn::Find() to find the function GetResource() implemented in the shared object. If we cannot find it, iFault will indicate the error. It is the responsability of the calling code to check the validity of the cDSkin object. Because we have used extern "C" when defining the function GetResource(), we don't have to deal with mangled name.

The method GetResourceL() shows how the resource will be retrieved from the shared object:

const tBitmapResource &cDSkin::GetResourceL(tSkinResource aResource)
{
   if(!iFault)
   {
      const tBitmapResource *lRes;

      lRes = (*iFunction)((tUint16)aResource);

      if(lRes)
         return *lRes;
      else
         throw uException(kErrNotFound,"cDSkin::GetResourceL");
   }
   else
      throw uException(iFault,"cDSkin::GetResourceL");
}

If the skin is not valid or if we cannot find the specified skin, an exception will be raised. The class uException is the basic exception class in the Zinzala SDK. It takes an error code and a string indicating where the exception was raised as its arguments.

You may have a look at the complete header and C++ files if you like.

Table of contents
  1. "Zinzala, Page 1/11"
  2. "Zinzala, Page 2/11"
  3. "Zinzala, Page 3/11"
  4. "Zinzala, Page 4/11"
  5. "Zinzala, Page 5/11"
  6. "Zinzala, Page 6/11"
  7. "Zinzala, Page 7/11"
  8. "Zinzala, Page 8/11"
  9. "Zinzala, Page 9/11"
  10. "Zinzala, Page 10/11"
  11. "Zinzala, Page 11/11"
e p (0)    12 Comment(s)

Technology White Papers

See More