July 30, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Writing BREW Extensions

  • April 21, 2005
  • By Ray Rischpater
  • Send Email »
  • More Articles »

The work done by the constructor leads to a lot of code, but as you see from the listing, other than a memory allocation it's really all bookkeeping. It begins by computing the size of the required result structure, which must be large enough to hold both private data for the object as well as its virtual table. Next, I allocate the necessary space, returning if the allocation fails or else zeroing the resulting memory (which isn't strictly necessary if your constructor is just going to fill out all of its member variables at this point). With the memory in hand, I find the location of the vtable, which sits after the static data (see Figure 2) in the newly created object, and then assign each of the method pointers in the vtable to the appropriate function. Finally, I initialize each of the data members and return the newly created object.

Figure 2: Identifying the vtable

Of course, every constructor deserves a well-balanced destructor, which falls into the Release method for the class:

static uint32 ITaskDatabase_Release(ITaskDatabase *p)
{
   STaskDatabaseData *pThis = (STaskDatabaseData *)p;

   if (!pThis ) return 0;

   pThis->nRefs--;
   if (pThis->nRefs != 0) return pThis->nRefs;

   RELEASEIF( pThis->pIShell );
   RELEASEIF( pThis->pIModule );

   FREE_VTBL(pThis, ITaskDatabase);

   FREEIF( pThis );

   return 0;
}

This function—which need have only file scope, because it's always accessed though the vtable anyway—simply decrements the reference count and either returns the new reference count, or frees the members of the object before releasing the object's vtable and the object itself. You should note the casting skullduggery that occurs between the single argument to release—the interface pointer—and the underlying data structure that contains the data associated with the interface instance. It's a bit of a hassle, and many times in looking at extensions written by others you may see a macro like this:

#define   THIS_FROM_INTERFACE(p, objtype) objtype *pThis = p;

I explicitly choose not to do that because I've found by coaching others that hiding the cast behind a macro only makes it harder to understand how an extension works for newcomers.

The remainder of your methods will look much like ITaskDatabase_Release: First convert the interface pointer into a pointer to the underlying representation, and then do whatever your method is supposed to do.

Summary

The BREW extension concept gives you a powerful mechanism with which to partition your code into components that can be shared between multiple applications. In addition to providing access to the same interface used by BREW components (making it easy for developers to learn to use your extensions), the platform provides the ability to offer extensions seamlessly through the BDS to both your own applications and those of other companies, letting you strike the perfect balance between internally sharing code and making your technologies available to other application developers in a profitable way.

For More Information

QUALCOMM BREW: http://www.qualcomm.com

QUALCOMM BREW Extensions: http://brew.qualcomm.com/brew/en/developer/resources/ad/extensions.html

About the Author

Ray Rischpater is the chief architect at Rocket Mobile, Inc., specializing in the design and development of messaging and information access applications for today's wireless devices. Ray Rischpater is the author of several books on software, including Development Including eBay Application Development and Software Development for the QUALCOMM BREW Platform, both available from Apress, and is an active Amateur Radio operator. Contact Ray at kf6gpe@lothlorien.com.





Page 3 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel