Using Standard Library and Floating Point Interfaces
The lack of a read/write segment, combined with some other platform restrictions forces Qualcomm to offer "helper functions" such as STRCPY
for strcpy, the C library string-copy function. Worse, there's no support for floating point arithmetic on floating-point numbers, because the ARM compiler brings in a floating-point library that requires (you guessed it) a read-write segment. Dealing with this problem can require three different approaches.
For fairly simple, standard C library calls, the easiest thing to do is provide a thin porting layer that re-implements the standard C call using a BREW helper function. (I prefer re-implementing these functions in this manner rather than changing the original implementation source.) While it's tempting to just start writing
#define strcpy(d, s) STRCPY(d, s)
I've begun advocating the use of inline functions, instead:
__inline char *strcpy(char *d, const char *s)
return STRCPY( d, s )
This has two key advantages:
- It permits you to control the size of your module by letting you decide which functions should actually be inlined (and in the process, you can also selectively debug a function if you so desire).
- It avoids the macro-variable problem. Because C macros pass their arguments by reference, not by value, side effects can result if the implementation of the macro uses any operation or function that mutates its value (such as the pre-increment or post-increment operators ++).
Unfortunately, the BREW API doesn't provide a full replacement of the C standard library; if you're looking for something like strtok
, you're out of luck. Over the years, I've gradually built a library of the unimplemented standard library functions I'm likely to encounter; experience has shown that I can probably implement and test something like isspace
faster than finding one, even with Google, and by keeping a library of these routines around, it's not that arduous a task.
However, if you're re-implementing a standard C library function, you should look out for two things. First, be sure to thoroughly unit test your implementation, and if possible, compare your implementation's behavior with the implementation of the original function on a platform such as UNIX or Windows! In point of fact, the isspace implementation I wrote went for years with a subtle bug (it didn’t treat \r as whitespace) that cost me a few hours of pain recently because I'd been too lazy to write exhaustive unit tests. Second, if you're going to draw from an existing source for your implementation, check license agreements thoroughly. Borrowing code from another library implementation can be very tempting, but can have drastic consequences on the legal ownership of your port thus causing untold business headaches later when you try to license the results. Take a look at the various licensing terms (GPL, LGPL, and so on) before simply scavenging code from other sources.
The problem with floating-point numbers is similar, but because you want to change what code gets invoked when the C compiler does its magic for operations such as * and /, it's a little trickier. Fortunately, Qualcomm has an excellent how-to in their Knowledge Base, complete with an object file you can link that replaces the default ARM-compiler provided floating-point arithmetic operators with ones that don't require a read-write segment. The only other change you need to make to your application is to invoke the function _fp_init() on startup to initialize the new floating-point routines, like this:
extern void _fp_init(void);
int AEEClsCreateInstance(AEECLSID cls, IShell *pishell,
IModule *pimodule, void **ppOut)
if (AEECLSID_MYCLS == cls )
return MyCls_New( piishell, pimodule, ppOut );
Using the Qualcomm-provided library does increase the size of your application slightly, but that's probably better than refactoring complex mathematical operations to invoke prefix functions like FADD
instead of infix operators like +
A final word of warning when it comes to floating-point variables: use them sparingly. While today's handsets seem remarkably fast if you've been doing mobile development for a number of years, they cannot hope to keep pace with any desktop platform. Floating-point mathematics on a wireless terminal can bring your application to a crawl, and devastate battery life at the same time. In practice, most of the best algorithms for mobile devices are implemented using domain-specific, fixed-point arithmetic operations for the best performance.