Problems and suggestions about individual projects should
go to users@thatproject.tigris.org

Introduction

Lightblue BREW C++ wrapper library (abbreviated as lbcw) is an
efficient C++ binding of Qualcomm's BREW SDK which is widely used for
developing mobile applications and games for CDMA mobile
platforms. QUALCOMM’s Binary Runtime Environment for
Wireless® (BREW®) follows an object-oriented design, which
exposes its functionality through BREW Interfaces. However, by some
reason, BREW Interfaces are declared as C structures instead of C++
classes. This makes them hard to use and extend. Nowadays, the
mobile platform becomes more powerful and makes the creation
of feature-rich applications possible. When the application
goes bigger and more complicated, the C API shows its limit.

The lbcw library make the developing of complex BREW applications and
extentions much easier by declaring all BREW interfaces into equivalent
C++ abstract classes without any speed slow down or executable size
increase. All
BREW Interfaces are used exactly as C++ objects.

The creation of BREW Extensions has never been easier; you can now
create your extension interfaces that are directly inherited from any
existing BREW Interfaces using the C++ inheritence.

Since version 0.8.6,
a copy of pre-generated header files are included in the lightblue
distribution which contains the C++ class declaration of all BREW
interfaces from BREW SDK 2.1.3 and 3.1.4. Any new SDKs will be
supported when they are released by Qualcomm.

Highlights

Ease of use. BREW Interfaces are now C++ Classes. Use or
extend (inherit) them as you do to C++ classes.

Extreme fast. There is absolute NO EXTRA COST of calling a
brew interface using the C++ syntax. For example
pIShell->Beep() and ISHELL_BEEP(pIShell) generates identical
assember code. Sometimes, it is even faster than the C implementation
by reducing unnecessary function call overheads. For example, the
HandleEvent() method of the IBrewApplet eliminates one level of
function call than the orignal implementation. Considering the high
frequency this method is being called, usally 30 to
40 CPU circles are saved per
second for an application updates itself frequently.

Compact executable size. For C++ programs that need
relocation, only a 140 bytes startup code is added to the beginning of
the mod file which relocate the function pointers and calls the
constructor of each global C++ objects before the entry point of the
MOD is called. However, since the Realview 2.x compiler is
supported, the generated assembler code to call virtual functions
reduced from 4 instruction to 3 instructions, which result in smaller
and faster code.

Features

Below is a list of features that the lbwc library are current
providing:

Accessing BREW Interfaces as C++ abstract classes

BREW Interfaces are C++ classes now. Their methods could be
accessed using the "." or "->"operator from the Interface instance.

Creating BREW Extensions by C++ inheritence

If you want to create a BREW Extension that exposes
interfaces extended from existing BREW Interfaces to other
applications, you just create a C++ class that inherited from that
Interface. No complicated macros and manual object memory
initialization is needed. All using the builtin C++ object creation
machenisms.

BREW Interfaces and C++ classes are interchangeable

Every functions that accepts a specific BREW Interface will also
accept the equivalent C++ wrapper class. For example, the
IDISPLAY_SetFont() method accepts an IFont interface as its last
parameter and the IFont interface's equivalent C++ wrapper class is
IBrewFont, you can write following code:

IDISPLAY_SetFont(pthis, (IFont*)MyFont); //MyFont is actually an
instance of IBrewFont.

Better compile time type checking and polymorphism

By reading the SDK document, we know that IUnzipAStream inherits from
IAStream. However, all this are logical, the compiler don't know this,
we have to explicitely cast an IUnzipAStream pointer to an IAStream
pointer to get it accept by a function that accept IAStream pointer.

When using the C++ wrapper classes, IBrewUnzipAStream class
is inherited form IBrewAStream. So every functions
that accepts an IAStream pointer will accept a pointer to
an instance of IUnzipAStream. By this facility, explicity type casting
is not as frequently used as it is in the C program.

Static and global variable supported

This major issue annoying the ADS compiler
users has been solved. Static and global
variables are now supported without any limitations. Global objects are
also supported whose constructor will be called before the entry point
of the mod is called.

Structure of the
library

The lbcw library contains two parts: the runtime and the BREW
Interfaces wrappers which is generated automatically by the lightblue
header generated(lbhg.exe).

The runtime part contains a single cpp file called "entryptr.cpp" which
is a replacement of AEEModGen.c and AEEAppGen.c. The
"entryptr.cpp" only contains less than 150 lines of code but does the
same job as AEEModGen.c and AEEAppGen.c that have 800+ lines of
source code in total. The result object file size
remains no differences or smaller.

The BREW Interfaces wrappers are automatically generated. They
are declared in "hpp" files that have the same base name as the
"h" files in the original BREW SDK. Two set of wrapper classes
are included in the lightblue distribution package:

Notes: When using these wrapper classes, the orginal BREW SDK is also
needed.

Why the wrapper
classes works

The wrapper classes do not contain or reference the BREW Interface it
wraps, but why it works?

The C++ compiler will create a hidden table which is often called
v-table ( virtual function table) for every class that has at least one
virtual function. When a vritual function is called, the actual
address of it is retrieved from the v-table at execution time. That's
why calling virtual functions is slower than calling non-virtual
functions whose address are known at compile time. For most
modern
C++ compilers, the v-table is implemented as an array of absolute
address to the virtual functions. For every instance of the class
that contains virtual functions, the first 4
bytes holds the address to its
v-table.

For example, if Class "CClass" has a virtual function
called "draw()" and "pClass" is a pointer to an instance of
CClass, when we call pClass->draw(), the compiler will generate
assembly code like following pseudo c code:

Let's go back to the implementation of the BREW Interfaces. The
method of BREW Interfaces can be called by macros that usually
has the following pattern: <CLASS_NAME>_<MethodName>(pthis,
...); For example, if you want to
call the Release() method of IGraphics, you type:
IGRAPHICS_Release(pIGraphics); the IGRAPHICS_Release() macro is expend
to

GET_PVTBL(p, IGraphics)->Release(p));

which in turn expends to:

((IGraphics*)p)->pvt ->Release(p);

pvt is the first field of IGraphics and is a 32bit pointer.
If we debug the code in assembly level, we can find that it
generates identical assembly code as a C++ virtual functions is
called.
Now let's seperate the above code in three lines of equivalent
code:

So if we declare a C++ class that contains identical methods as a BREW
Interface and declare these methods as the same order as they are
declared in the BREW Interface, the v-table of the C++ class
will identical to the BREW Interface. We can thus use this
C++ class as a wrapper class of the BREW Interface.