Forums | developer.brewmp.com Forums | developer.brewmp.com

Developer

Forums

Forums:

Hello guys, I'm new to BREW today. I got hired to be a full time brew developer it seems, so im kind of wary of jumping right in and starting building apps that will get deployed right away. I'm just wondering if some of you experienced BREW developers can give me some heads up about things i should avoid and others that i should look into with BREW development.

Immediate questions i have:

1. C vs C++ ( i dont mind working with either....but am i going to run into a big hit with C++ and OOP? )

2. Public BREW code libraries. ( i've read that i should stay away from stuff like the STL, are there any libraries that developers find increase productivity, preferable public domain code/BSD licence. I'm interested in helping with a widget library or something)

3. Things to stay away from in the BREW API. (It happends with every API...fetures might seem nice and good, but prove to be more pain then they are worth in the long run)

Any other things you can add would be of great help to me...and i'm sure alot of the new BREW developers trying to start off. Post Things that work...and Things that Dont.

Thanks for all the help in advance.

Quote:only one ISHELL_PostEvent at a time
If you want to send yourself multiple command events but don't care what order they arrive in, you would think you could post them all at the same time. For example:
code:
case EVT_APP_START:
ISHELL_PostEvent(pMe->a.m_pIShell, AEECLSID_HELLOWORLD, EVT_COMMAND, EVT_USER+100, 0);
ISHELL_PostEvent(pMe->a.m_pIShell, AEECLSID_HELLOWORLD, EVT_COMMAND, EVT_USER+101, 0);
...
However, you'll only receive the first event. The next one never comes.
It turns out that BREW *requires* you to chain them:
code:
switch (eCode)
{
case EVT_APP_START:
ISHELL_PostEvent(pMe->a.m_pIShell, AEECLSID_HELLOWORLD, EVT_COMMAND, EVT_USER+100, 0);
...
break;
case EVT_COMMAND:
if (wParam == EVT_USER+100)
ISHELL_PostEvent(pMe->a.m_pIShell, AEECLSID_HELLOWORLD, EVT_COMMAND, EVT_USER+101, 0);
else if (wParam == EVT_USER+101)
...
...
break;
I think this is a bug, but... whatever. This behavior is true in the emulator and on at least one handset.
Just thought you'd like to know.
--t

Quote:only one ISHELL_PostEvent at a time
If you want to send yourself multiple command events but don't care what order they arrive in, you would think you could post them all at the same time. For example:
code:
case EVT_APP_START:
ISHELL_PostEvent(pMe->a.m_pIShell, AEECLSID_HELLOWORLD, EVT_COMMAND, EVT_USER+100, 0);
ISHELL_PostEvent(pMe->a.m_pIShell, AEECLSID_HELLOWORLD, EVT_COMMAND, EVT_USER+101, 0);
...
However, you'll only receive the first event. The next one never comes.
It turns out that BREW *requires* you to chain them:
code:
switch (eCode)
{
case EVT_APP_START:
ISHELL_PostEvent(pMe->a.m_pIShell, AEECLSID_HELLOWORLD, EVT_COMMAND, EVT_USER+100, 0);
...
break;
case EVT_COMMAND:
if (wParam == EVT_USER+100)
ISHELL_PostEvent(pMe->a.m_pIShell, AEECLSID_HELLOWORLD, EVT_COMMAND, EVT_USER+101, 0);
else if (wParam == EVT_USER+101)
...
...
break;
I think this is a bug, but... whatever. This behavior is true in the emulator and on at least one handset.
Just thought you'd like to know.
--t

I use C++ and I don't feel its too bloated, etc. I tend to use a lot of function pointers in C anyway, so it probably isn't even slower for me. Display access and File access tend to be the major slow points, not function calls or a few extra bytes of memory. Design carefully, however, since you are working on an embedded system. All sorts of tricks that work on a platform with virtual memory and a hard disk won't work here.
I stay away from all of the BREW UI controls. They are a little ugly, they work differently on each platform, and they never do exactly what you need. I've written my own controls which I can tailor for each application.
I haven't looked at any open source UI toolkits; my guess is they are targeted more for the desktop Look/Feel. Do you know of any that are designed for highly embedded systems?

I use C++ and I don't feel its too bloated, etc. I tend to use a lot of function pointers in C anyway, so it probably isn't even slower for me. Display access and File access tend to be the major slow points, not function calls or a few extra bytes of memory. Design carefully, however, since you are working on an embedded system. All sorts of tricks that work on a platform with virtual memory and a hard disk won't work here.
I stay away from all of the BREW UI controls. They are a little ugly, they work differently on each platform, and they never do exactly what you need. I've written my own controls which I can tailor for each application.
I haven't looked at any open source UI toolkits; my guess is they are targeted more for the desktop Look/Feel. Do you know of any that are designed for highly embedded systems?

1. You can use either of C/C++. RVCT C++ compiler supports embedded C++ specification.
2. In C++ code make sure that you override new/delete. It may be convenient to override in global scope instead of per class basis. If you are planning to use array new/delete for your class then make sure that you override vector new/delete, otherwise ARM compiler will complain.
3. You can not have global function pointer arrays.
4. Array of strings declaration is little tricky. You need to specify the dimension.
5. Watch out for file write. There is no asynchronous file write.
6. If your program blocks control for more than 60 sec, phone will reset by hardware watch dog timer.
7. BREW sockets are BSD style but asynchronous.
I will update this list as I find time.
ruben

1. You can use either of C/C++. RVCT C++ compiler supports embedded C++ specification.
2. In C++ code make sure that you override new/delete. It may be convenient to override in global scope instead of per class basis. If you are planning to use array new/delete for your class then make sure that you override vector new/delete, otherwise ARM compiler will complain.
3. You can not have global function pointer arrays.
4. Array of strings declaration is little tricky. You need to specify the dimension.
5. Watch out for file write. There is no asynchronous file write.
6. If your program blocks control for more than 60 sec, phone will reset by hardware watch dog timer.
7. BREW sockets are BSD style but asynchronous.
I will update this list as I find time.
ruben

ISHELL_PostEventEx() is part of the API since 2.1:
Description:
This function posts an asynchronous event to the specified app. This function is very similar to ISHELL_PostEvent(). The main difference is that this function allows multiple events of the same type (same event code) to be posted and pending to be dispatched for the same app
"If you want to send yourself multiple command events but don't care what order they arrive in..." - you are guaranteed to get the callbacks & posted events in the order in which you registered for them
HTH
Radu

ISHELL_PostEventEx() is part of the API since 2.1:
Description:
This function posts an asynchronous event to the specified app. This function is very similar to ISHELL_PostEvent(). The main difference is that this function allows multiple events of the same type (same event code) to be posted and pending to be dispatched for the same app
"If you want to send yourself multiple command events but don't care what order they arrive in..." - you are guaranteed to get the callbacks & posted events in the order in which you registered for them
HTH
Radu

Quote:Originally posted by ruben
2. In C++ code make sure that you override new/delete. It may be convenient to override in global scope instead of per class basis. If you are planning to use array new/delete for your class then make sure that you override vector new/delete, otherwise ARM compiler will complain.
Quote:Originally posted by aisaksen
My new, new[], delete, delete[], and __assert are defined as follows. These are the standard BREW way to do it that has been mentioned in a few other threads.
void* operator new(size_t sz)
{
return MALLOC(sz);

void operator delete(void *p)
{
FREE(p);

void* operator new[](size_t sz)
{
return MALLOC(sz);
}
void operator delete[](void *p)
{
FREE(p);

extern "C" void __assert(const char * , const char * , int ) {
}
-Aaron

Quote:Originally posted by ruben
2. In C++ code make sure that you override new/delete. It may be convenient to override in global scope instead of per class basis. If you are planning to use array new/delete for your class then make sure that you override vector new/delete, otherwise ARM compiler will complain.
Quote:Originally posted by aisaksen
My new, new[], delete, delete[], and __assert are defined as follows. These are the standard BREW way to do it that has been mentioned in a few other threads.
void* operator new(size_t sz)
{
return MALLOC(sz);

void operator delete(void *p)
{
FREE(p);

void* operator new[](size_t sz)
{
return MALLOC(sz);
}
void operator delete[](void *p)
{
FREE(p);

extern "C" void __assert(const char * , const char * , int ) {
}
-Aaron

regarding display performance, avoid IImage as it is too slow
and also, some of its functions (like SetDrawSize) behave strangely in some phones
and sound support (at least in BREW 1.1) has several issues from device to device.

regarding display performance, avoid IImage as it is too slow
and also, some of its functions (like SetDrawSize) behave strangely in some phones
and sound support (at least in BREW 1.1) has several issues from device to device.

If you want to make games, i'd say that C is a better choice. Try to use CONVERTBMP instead of Images, and do not load all your pictures at the same time (dogwatch).
I'd also recommand to use two timers to reloop, thus you will have better results (especially on the lg6000) and the dog will be happy (A530).
Make your own malloc routine for debugging purpose, and try to use some __LINE__ and __FILE__ in it, so you will save time when you'll be trying to find out which functions do not free memory..
/kUfa

If you want to make games, i'd say that C is a better choice. Try to use CONVERTBMP instead of Images, and do not load all your pictures at the same time (dogwatch).
I'd also recommand to use two timers to reloop, thus you will have better results (especially on the lg6000) and the dog will be happy (A530).
Make your own malloc routine for debugging purpose, and try to use some __LINE__ and __FILE__ in it, so you will save time when you'll be trying to find out which functions do not free memory..
/kUfa

i've got one!
this style crashed my get it now/file system of my phone! i couldn't access the get it now menu and i had to send the phoen to qualcomm.
dragging multiple files and dropping them once on the apploader!
now, i don't do this, i just drag and drop one file at a time on the apploader.

i've got one!
this style crashed my get it now/file system of my phone! i couldn't access the get it now menu and i had to send the phoen to qualcomm.
dragging multiple files and dropping them once on the apploader!
now, i don't do this, i just drag and drop one file at a time on the apploader.

Quote:Make your own malloc routine for debugging purpose, and try to use some __LINE__ and __FILE__ in it, so you will save time when you'll be trying to find out which functions do not free memory..
sorry, can anybody explain me what he've tried to say? :confused:

Quote:Make your own malloc routine for debugging purpose, and try to use some __LINE__ and __FILE__ in it, so you will save time when you'll be trying to find out which functions do not free memory..
sorry, can anybody explain me what he've tried to say? :confused:

Maybe that will help :
#define GAllocMem(app,type) ((type*) iGAllocMem(app, sizeof(type), __FILE__, __FUNCTION__, __LINE__))
// ....
void *iGAllocMem(Application *app, int32 size, char *name, char *function, int32 line)
{
MemNode *res;
if(res = (MemNode*)MALLOC(size + sizeof(MemNode)))
{
res->line = line;
res->name = name;
res->function = function;
res->prev = NULL;
res->next = firstMemNode;
if(firstMemNode)
firstMemNode->prev = res;
firstMemNode = res;
//IDAOUT3("**ALLOC: %d bytes (%s line %d)", size, name, line);
return res + 1;
}
else
{
IDAOUT("** Not enough memory");
IDAOUT1(" {%s}", name);
IDAOUT2(" %s -- Line %d", function, line);
IDAOUT(" Memory used :");
IDAOUT1(" -- %d bytes --", IHEAP_GetMemStats(app->platformSpecific.heap));
}
return NULL;

I let you guess how the application and the memnode struct look like..
/kUfa

Maybe that will help :
#define GAllocMem(app,type) ((type*) iGAllocMem(app, sizeof(type), __FILE__, __FUNCTION__, __LINE__))
// ....
void *iGAllocMem(Application *app, int32 size, char *name, char *function, int32 line)
{
MemNode *res;
if(res = (MemNode*)MALLOC(size + sizeof(MemNode)))
{
res->line = line;
res->name = name;
res->function = function;
res->prev = NULL;
res->next = firstMemNode;
if(firstMemNode)
firstMemNode->prev = res;
firstMemNode = res;
//IDAOUT3("**ALLOC: %d bytes (%s line %d)", size, name, line);
return res + 1;
}
else
{
IDAOUT("** Not enough memory");
IDAOUT1(" {%s}", name);
IDAOUT2(" %s -- Line %d", function, line);
IDAOUT(" Memory used :");
IDAOUT1(" -- %d bytes --", IHEAP_GetMemStats(app->platformSpecific.heap));
}
return NULL;

I let you guess how the application and the memnode struct look like..
/kUfa

btw i vote for this thread since it's a very good idea and all new users should read it! Well done jord!

btw i vote for this thread since it's a very good idea and all new users should read it! Well done jord!

thanks for the explanation! :) i was really useful! :) :cool:

thanks for the explanation! :) i was really useful! :) :cool:

As this topic is about newbies :), i have a question:
I worked with java so i'm used using and handling exceptions, any experienced user of brew recommend using exceptions in brew? because maybe the overhead of throwing and handling is simply replaced with an error code...

As this topic is about newbies :), i have a question:
I worked with java so i'm used using and handling exceptions, any experienced user of brew recommend using exceptions in brew? because maybe the overhead of throwing and handling is simply replaced with an error code...

Well, as far I know arm C++ does not support exception handling.. Then it totally depends on the way you prefer to implement errors; ususally what i do is to have a int8 return value in all my "critical" functions, ie all of them that alloc mem / access files /etc.. So basically if there is an error somewhere, it will give it to all the calling functions, which can handle it.. Btw sorry if my english is not that good hehe
:D

Well, as far I know arm C++ does not support exception handling.. Then it totally depends on the way you prefer to implement errors; ususally what i do is to have a int8 return value in all my "critical" functions, ie all of them that alloc mem / access files /etc.. So basically if there is an error somewhere, it will give it to all the calling functions, which can handle it.. Btw sorry if my english is not that good hehe
:D

sorry bothering u but u know if ARM compiler supports the directive #pragma?
because its much more clean and simple to write:
#pragma once
instead of
----------------------------------------------------- Object.h
#ifndef OBJECT_H
#define OBJECT_H
class Object {
...
;
#endif
----------------------------------------------------- Object.h
thanks :)

sorry bothering u but u know if ARM compiler supports the directive #pragma?
because its much more clean and simple to write:
#pragma once
instead of
----------------------------------------------------- Object.h
#ifndef OBJECT_H
#define OBJECT_H
class Object {
...
;
#endif
----------------------------------------------------- Object.h
thanks :)

RVCT ARM compiler support #pragma directive. Following pragma names are available to use
arm section
check_printf_formats
check_scanf_formats
debug
import
Ospace
Otime
Onum
Please refer compiler doc for further information.
ruben

RVCT ARM compiler support #pragma directive. Following pragma names are available to use
arm section
check_printf_formats
check_scanf_formats
debug
import
Ospace
Otime
Onum
Please refer compiler doc for further information.
ruben

Ya this thread rules. Are there any admins on this board that could make it a sticky thread?

Ya this thread rules. Are there any admins on this board that could make it a sticky thread?

Another one (thanks dragon):
Do not use ISOUNDPLAYER_Set but ISOUNDPLAYER_SetInfo, since it's deprecated and will not work on some phones (lg6000 for instance)
/kUfa

Another one (thanks dragon):
Do not use ISOUNDPLAYER_Set but ISOUNDPLAYER_SetInfo, since it's deprecated and will not work on some phones (lg6000 for instance)
/kUfa

Few more items:
1. When you use IWEB_GetResponse, don't declare your URL on stack. Refer SDK "Important information about WEBOPT lifetimes" for more info. This is very commonly made mistake.
2. If you are doing lots of file write, write in relatively bigger chunks (anything between 2k to 4k) is the best, rather than multiple small chunks.
3. You can use const data if you are using C++
I will add more as I find time.
ruben

Few more items:
1. When you use IWEB_GetResponse, don't declare your URL on stack. Refer SDK "Important information about WEBOPT lifetimes" for more info. This is very commonly made mistake.
2. If you are doing lots of file write, write in relatively bigger chunks (anything between 2k to 4k) is the best, rather than multiple small chunks.
3. You can use const data if you are using C++
I will add more as I find time.
ruben

One other common problem that i have in mind: use transparent images if you decide to use BitBlt with negative offsets on the t720..
/kUfa
PS: this thread rocks!

One other common problem that i have in mind: use transparent images if you decide to use BitBlt with negative offsets on the t720..
/kUfa
PS: this thread rocks!

Make sure to clip your image blits on ANY handset.
kUfa: I completely disagree with you regarding the usage of C only for games. It always depends on the application, nothing else. There are games I did in C on Brew and some I did in C++ becasue they were so much more complex. It is a myth that C++ is intrinsically slower than C, if that's what you were suggesting. There are plenty fo cases where it is actually performing much better than C because of the implicit code architecture.

Make sure to clip your image blits on ANY handset.
kUfa: I completely disagree with you regarding the usage of C only for games. It always depends on the application, nothing else. There are games I did in C on Brew and some I did in C++ becasue they were so much more complex. It is a myth that C++ is intrinsically slower than C, if that's what you were suggesting. There are plenty fo cases where it is actually performing much better than C because of the implicit code architecture.

We are not making very advanced games, are we? Ie you can make a descent or quake only using c, it works fine, and i really do not think it's a problem not to use c++. Of course, if you are very used to OOP and c++, then use c++, you will have smaller developement time.
And nope, it s not a myth. Check the output assembly code, you will see. If you are not using specific c++ functionalities, yep, it will run at the same speed, but why use c++ then? Check http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1359.pdf
But you are true, it depends on the application. On none of my games i needed some c++ functionalities, so i usually prefer fast games instead of "uml-compliant" applications! Btw, it was just an advice, everybody is smart enough to take his own choices.
/kUfa

We are not making very advanced games, are we? Ie you can make a descent or quake only using c, it works fine, and i really do not think it's a problem not to use c++. Of course, if you are very used to OOP and c++, then use c++, you will have smaller developement time.
And nope, it s not a myth. Check the output assembly code, you will see. If you are not using specific c++ functionalities, yep, it will run at the same speed, but why use c++ then? Check http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1359.pdf
But you are true, it depends on the application. On none of my games i needed some c++ functionalities, so i usually prefer fast games instead of "uml-compliant" applications! Btw, it was just an advice, everybody is smart enough to take his own choices.
/kUfa

An interesting article on the C vs C++ topic
http://www.cuj.com/documents/s=8010/cuj0208stroustr/

An interesting article on the C vs C++ topic
http://www.cuj.com/documents/s=8010/cuj0208stroustr/

I'm not even getting into this discussion. Do what you think is right.

I'm not even getting into this discussion. Do what you think is right.

This thread rocks! I'm a newb with familiarity of Palm, RIM, WinCE, and some J2ME and all the information described is extremely telling for me. I hope to have info to contribute to this thread. I normally keep my own list of "programming secrets" just to be efficient in case I forget a trick.

This thread rocks! I'm a newb with familiarity of Palm, RIM, WinCE, and some J2ME and all the information described is extremely telling for me. I hope to have info to contribute to this thread. I normally keep my own list of "programming secrets" just to be efficient in case I forget a trick.

Quote:Originally posted by Tellarin
regarding display performance, avoid IImage as it is too slow
and also, some of its functions (like SetDrawSize) behave strangely in some phones
and sound support (at least in BREW 1.1) has several issues from device to device.
Whats the alternative to using IIMAGE? IDISPLAY_BitBlt()? It would seem strange though that the API functions are slow. Wouldn't Qualcomm want to make these sort of functions as fast as possible in this enviroment?

Quote:Originally posted by Tellarin
regarding display performance, avoid IImage as it is too slow
and also, some of its functions (like SetDrawSize) behave strangely in some phones
and sound support (at least in BREW 1.1) has several issues from device to device.
Whats the alternative to using IIMAGE? IDISPLAY_BitBlt()? It would seem strange though that the API functions are slow. Wouldn't Qualcomm want to make these sort of functions as fast as possible in this enviroment?

In BREW 1.1 you can use CONVERTBMP, BitBlt and in BREW 2.0 or above you can use IBitmap interface.
ruben

In BREW 1.1 you can use CONVERTBMP, BitBlt and in BREW 2.0 or above you can use IBitmap interface.
ruben

Quote:Originally posted by slip
Whats the alternative to using IIMAGE? IDISPLAY_BitBlt()? It would seem strange though that the API functions are slow. Wouldn't Qualcomm want to make these sort of functions as fast as possible in this enviroment?
another reason not to use IIMAGE
http://brewforums.qualcomm.com/showthread.php?s=&threadid=2307
not sure, this might just be my problem.

Quote:Originally posted by slip
Whats the alternative to using IIMAGE? IDISPLAY_BitBlt()? It would seem strange though that the API functions are slow. Wouldn't Qualcomm want to make these sort of functions as fast as possible in this enviroment?
another reason not to use IIMAGE
http://brewforums.qualcomm.com/showthread.php?s=&threadid=2307
not sure, this might just be my problem.

Indeed BREW does not support exceptions, as a C++ and Java developer
it was "nostalgic" to go back to return integers as error codes
but it's nice :)

Indeed BREW does not support exceptions, as a C++ and Java developer
it was "nostalgic" to go back to return integers as error codes
but it's nice :)

Issues when using C++ conventions in a BREW environment
Interested in using an OO paradigm as much as possible? Here are some issues:
1) If code is written well in an OO sense, it tends to use more stack frames, for reasons which include the following:
i) One of OOP's first principles is to group code into functions for clarity's sake. For example, take some class that has an onEvent(ecode) method. It may make sense to group the functionality for each event into a separate method, like this:
onEvent(ecode) {
switch(ecode) {
case EVT_1:
onEvt1();
break;
case EVT_2:
onEvt2();
break;
...
case EVT_N:
onEvtN();
break;
}
}
It's 'cleaner' code this way, especially if each subprocedure is particularly complex. In general, this is a good idea. Only one new method's overhead was added on to the stack for each event. However, if this technique is used in a few extra places without careful planning, a program in a BREW environment can quickly be hit with slow performance and memory allocation problems.
In other words, weigh the additional overhead costs against the benefits from the added clarity that the implementation provides.
ii) Classes tend to pass functionality along to members. For example, consider a Canvas class that has a draw(display) method, and suppose it has an array of Widget objects that each draw some graphical object to the screen. Correct OOP would be to give Widget a draw(display) method as well, so that you can do this:
Canvas::draw(display) {
for i = 0 to n:
widget[i].draw(display);
}
Again, in general doing things this way is no big deal - and even correct - in terms of OOP design. But there is additional overhead for each call to widget.draw(display). In the worst case, each widget may have widgets of its own for which draw(display) is called. Nothing wrong with that in an OO sense, but in a BREW environment there may be too many calls on the stack and slow performance.
2) The classes used in BREW (such as AEEApplet generated in AEEAppGen.c) are not classes in the C++ sense. Some C++ functionality is only partial or not implemented, so special care must be taken when deriving subclasses.
i) Virtual functionality does not work according to C++ specs for members of these BREW API-derived classes. Consider these classes:
class BaseApplet : public AEEApplet
{
....
void onInit() {
c = new DerivedCanvas();
}
void onEvent(ecode) {
c->onEvent(ecode); // this will cause an exception...
}
private:
Canvas *c;
}
class Canvas
{
public:
virtual void onEvent(ecode) = 0;
}
class DerivedCanvas
{
public:
void onEvent(ecode) { do something...}
}
An exception is thrown when c->onEvent(ecode) is attempted. Note that if BaseApplet were not an AEEApplet, everything would work fine (in other words, virtual functionality works so long as the parent class is not derived from a BREW module).
3) Constructors are not called for members of these BREW API-derived classes. Again consider some BaseApplet class, derived from AEEApplet:
class BaseApplet : public AEEApplet
{
....
BaseApplet() { DBGPRINTF("BaseApplet"); }
private:
DataItem d;
}
class DataItem
{
public:
DataItem() { DBGPRINTF("DataItem()");
}
In VStudio 7.0 IDE (and presumably in other environments as well), neither the strings "BaseApplet()" nor "DataItem()" will appear in the debug window.
Lastly, here is a link to a document that describes the C++ language conventions supported by the ARM compiler for BREW, in particular, note that exceptions and templates are not supported.
http://www.arm.com/pdfs/DUI0171B_RVCT_BREW_CompLib.pdf

Issues when using C++ conventions in a BREW environment
Interested in using an OO paradigm as much as possible? Here are some issues:
1) If code is written well in an OO sense, it tends to use more stack frames, for reasons which include the following:
i) One of OOP's first principles is to group code into functions for clarity's sake. For example, take some class that has an onEvent(ecode) method. It may make sense to group the functionality for each event into a separate method, like this:
onEvent(ecode) {
switch(ecode) {
case EVT_1:
onEvt1();
break;
case EVT_2:
onEvt2();
break;
...
case EVT_N:
onEvtN();
break;
}
}
It's 'cleaner' code this way, especially if each subprocedure is particularly complex. In general, this is a good idea. Only one new method's overhead was added on to the stack for each event. However, if this technique is used in a few extra places without careful planning, a program in a BREW environment can quickly be hit with slow performance and memory allocation problems.
In other words, weigh the additional overhead costs against the benefits from the added clarity that the implementation provides.
ii) Classes tend to pass functionality along to members. For example, consider a Canvas class that has a draw(display) method, and suppose it has an array of Widget objects that each draw some graphical object to the screen. Correct OOP would be to give Widget a draw(display) method as well, so that you can do this:
Canvas::draw(display) {
for i = 0 to n:
widget[i].draw(display);
}
Again, in general doing things this way is no big deal - and even correct - in terms of OOP design. But there is additional overhead for each call to widget.draw(display). In the worst case, each widget may have widgets of its own for which draw(display) is called. Nothing wrong with that in an OO sense, but in a BREW environment there may be too many calls on the stack and slow performance.
2) The classes used in BREW (such as AEEApplet generated in AEEAppGen.c) are not classes in the C++ sense. Some C++ functionality is only partial or not implemented, so special care must be taken when deriving subclasses.
i) Virtual functionality does not work according to C++ specs for members of these BREW API-derived classes. Consider these classes:
class BaseApplet : public AEEApplet
{
....
void onInit() {
c = new DerivedCanvas();
}
void onEvent(ecode) {
c->onEvent(ecode); // this will cause an exception...
}
private:
Canvas *c;
}
class Canvas
{
public:
virtual void onEvent(ecode) = 0;
}
class DerivedCanvas
{
public:
void onEvent(ecode) { do something...}
}
An exception is thrown when c->onEvent(ecode) is attempted. Note that if BaseApplet were not an AEEApplet, everything would work fine (in other words, virtual functionality works so long as the parent class is not derived from a BREW module).
3) Constructors are not called for members of these BREW API-derived classes. Again consider some BaseApplet class, derived from AEEApplet:
class BaseApplet : public AEEApplet
{
....
BaseApplet() { DBGPRINTF("BaseApplet"); }
private:
DataItem d;
}
class DataItem
{
public:
DataItem() { DBGPRINTF("DataItem()");
}
In VStudio 7.0 IDE (and presumably in other environments as well), neither the strings "BaseApplet()" nor "DataItem()" will appear in the debug window.
Lastly, here is a link to a document that describes the C++ language conventions supported by the ARM compiler for BREW, in particular, note that exceptions and templates are not supported.
http://www.arm.com/pdfs/DUI0171B_RVCT_BREW_CompLib.pdf

1)Personally I cannot understand the relationship between stack exhaustion and "slow performance and memory allocation problems". And BTW - there is nothing related to OOP in 1)
2) Presumably
class DerivedCanvas : public Canvas;
I see nothing wrong with
c->onEvent(ecode);
Maybe you can offer some details (what exception. in what conditions was it thrown, was it in simulator or a specific device, etc)
3) Indeed - BaseApplet is POD (plain old data) as it comes from plain C.
The cited document clearly states: "templates are partially supported". There are lots of threads debating this issue.
HTH

1)Personally I cannot understand the relationship between stack exhaustion and "slow performance and memory allocation problems". And BTW - there is nothing related to OOP in 1)
2) Presumably
class DerivedCanvas : public Canvas;
I see nothing wrong with
c->onEvent(ecode);
Maybe you can offer some details (what exception. in what conditions was it thrown, was it in simulator or a specific device, etc)
3) Indeed - BaseApplet is POD (plain old data) as it comes from plain C.
The cited document clearly states: "templates are partially supported". There are lots of threads debating this issue.
HTH

Radub,
Thanks for your feedback. :o
Apologies for being vague. By 'performance and memory allocation problems', I meant that the more methods are nested, the greater the risk of overflowing the stack. This is only a memory problem if total memory allocation is tied to stack usage - that is, if an app's total available memory is decremented a bit every time a method is invoked and pushed onto the stack. If memory allocation isn't tied to the stack in this way, then this isn't an issue.
I consider grouping of code for clarity's sake a good reason to use OOP. I find I am able to organize my code in a more intuitive way than with other language paradigms. Of course, this is a subjective opinion and there's no sense debating it. My point is simply that if you are a person who uses OOP in a similar way and you understand my rationale, then be careful when you attempt to apply these strategies in a Brew environment.
Regarding the virtual call, thanks for the correction. DerivedCanvas is indeed a public Canvas. (My original, tested code reflected this :) ) I wish I could help further, but all I know for sure is that I get an access violation when c->onEvent(ecode) is called. I've attempted executing this code in the Brew emulator and Visual C++ Studio 7.0 - it didn't depend on what device was loaded in the emulator at the time.

Radub,
Thanks for your feedback. :o
Apologies for being vague. By 'performance and memory allocation problems', I meant that the more methods are nested, the greater the risk of overflowing the stack. This is only a memory problem if total memory allocation is tied to stack usage - that is, if an app's total available memory is decremented a bit every time a method is invoked and pushed onto the stack. If memory allocation isn't tied to the stack in this way, then this isn't an issue.
I consider grouping of code for clarity's sake a good reason to use OOP. I find I am able to organize my code in a more intuitive way than with other language paradigms. Of course, this is a subjective opinion and there's no sense debating it. My point is simply that if you are a person who uses OOP in a similar way and you understand my rationale, then be careful when you attempt to apply these strategies in a Brew environment.
Regarding the virtual call, thanks for the correction. DerivedCanvas is indeed a public Canvas. (My original, tested code reflected this :) ) I wish I could help further, but all I know for sure is that I get an access violation when c->onEvent(ecode) is called. I've attempted executing this code in the Brew emulator and Visual C++ Studio 7.0 - it didn't depend on what device was loaded in the emulator at the time.

You might get an access violation due to uninitialized c - your code should be at least:
if (c)
c->onEvent(ecode);
HTH

You might get an access violation due to uninitialized c - your code should be at least:
if (c)
c->onEvent(ecode);
HTH

I found the problem with my previous post regarding virtual function calls from top level BREW API-derived classes. The access violation had nothing to do with the fact that the parent class was BREW API-derived. I was doing this:
BaseClass {
public:
virtual void test() = 0;
};
DerivedClass {
public:
void test() { do something }
};
BaseClass *baseClass;
DerivedClass derivedClass;
baseClass = &derivedClass;
baseClass->test(); // this is an illegal call
However, baseClass->test() succeeds if new is called for baseClass:
BaseClass *baseClass;
baseClass = new DerivedClass();
baseClass->test(); // this is ok
Sorry about the confusion.

I found the problem with my previous post regarding virtual function calls from top level BREW API-derived classes. The access violation had nothing to do with the fact that the parent class was BREW API-derived. I was doing this:
BaseClass {
public:
virtual void test() = 0;
};
DerivedClass {
public:
void test() { do something }
};
BaseClass *baseClass;
DerivedClass derivedClass;
baseClass = &derivedClass;
baseClass->test(); // this is an illegal call
However, baseClass->test() succeeds if new is called for baseClass:
BaseClass *baseClass;
baseClass = new DerivedClass();
baseClass->test(); // this is ok
Sorry about the confusion.

Assuming DerivedClass publicly inherits from BaseClass I still don't see your problem with the first snippet.

Assuming DerivedClass publicly inherits from BaseClass I still don't see your problem with the first snippet.

The first snippet does work, Radub. it won't work if the baseClass pointer is assigned to the address of an existing derived instance - which is what my original code was doing and why I was getting an exception.

The first snippet does work, Radub. it won't work if the baseClass pointer is assigned to the address of an existing derived instance - which is what my original code was doing and why I was getting an exception.

My point is that:
Derived d;
Base& b = d;
b.test();
(or the pointer version) should work too

My point is that:
Derived d;
Base& b = d;
b.test();
(or the pointer version) should work too

me too...i thought you could do that too, but i get access violations when i try it, (regardless of whether it's a BREW API or generic class). No idea why...is this part of the C++ specifications?

me too...i thought you could do that too, but i get access violations when i try it, (regardless of whether it's a BREW API or generic class). No idea why...is this part of the C++ specifications?

Ok, at this point I really think I found a bug here. In straight C++, I tested the scenario where a pointer to a base class is assigned the address of a derived class and then a virtual function is called (that is defined in the derived class). Works fine. The C++ specs let you do this with no problem.
Then in a BREW environment I set up an identical situation. I'm uploading the code and I hope others will test this code on their systems to verify this produces an access violation in a BREW environment.
Also, I found that if the base class pointer and derived class instances are instantiated locally (instead of members of the parent class), the access violation doesn't occur. Very strange behavior...

Ok, at this point I really think I found a bug here. In straight C++, I tested the scenario where a pointer to a base class is assigned the address of a derived class and then a virtual function is called (that is defined in the derived class). Works fine. The C++ specs let you do this with no problem.
Then in a BREW environment I set up an identical situation. I'm uploading the code and I hope others will test this code on their systems to verify this produces an access violation in a BREW environment.
Also, I found that if the base class pointer and derived class instances are instantiated locally (instead of members of the parent class), the access violation doesn't occur. Very strange behavior...

There is no mistery here. AEEBridge is POD - meaning that it doesn't respect C++ rules: no constructor is ever called for your Derived class. When calling
derived->test()
derived is not fully constructed and triggers the exception.
HTH

There is no mistery here. AEEBridge is POD - meaning that it doesn't respect C++ rules: no constructor is ever called for your Derived class. When calling
derived->test()
derived is not fully constructed and triggers the exception.
HTH

Definitely something to keep in mind when developing Brew apps in C++.

Definitely something to keep in mind when developing Brew apps in C++.

Do BREW target support bit-fields? (E.g., struct s { uint f1:1, uint f2:2 ... }; )
thanks,
mike

Do BREW target support bit-fields? (E.g., struct s { uint f1:1, uint f2:2 ... }; )
thanks,
mike

Bitfields have been part of the C-language since its first incarnation way back when. As a result as is readily available in compilers as the == operator for example. There's nothing exotic about them.

Bitfields have been part of the C-language since its first incarnation way back when. As a result as is readily available in compilers as the == operator for example. There's nothing exotic about them.

Yeah, I remember :)
I thought I had problems with really bad bitfield code generation at one point, but
I could be mistaken. (Then again, I think it was an ARM600 or something.)
Thanks

Yeah, I remember :)
I thought I had problems with really bad bitfield code generation at one point, but
I could be mistaken. (Then again, I think it was an ARM600 or something.)
Thanks

Hi,
I just read this thread because of the new/delete overload
Does MALLOC and FREE work in C++?
As far as i know you can't do MALLOC(sizeof(CTest)) to alloc a class, and all that the overloaded new and delete do is call MALLOC and FREE with the parameter received.
Do MALLOC and FREE (from Brew) behave differently from the ones in C ?
Thanks

Hi,
I just read this thread because of the new/delete overload
Does MALLOC and FREE work in C++?
As far as i know you can't do MALLOC(sizeof(CTest)) to alloc a class, and all that the overloaded new and delete do is call MALLOC and FREE with the parameter received.
Do MALLOC and FREE (from Brew) behave differently from the ones in C ?
Thanks

MALLOC and FREE works in C++. However if you call MALLOC/FREE for a class, constructor/destructor will never get called (that's how standard C++ works). That's why there is new/delete which will call constructor and destructor.
Take a decent C/C++ book and read about object allocation.

MALLOC and FREE works in C++. However if you call MALLOC/FREE for a class, constructor/destructor will never get called (that's how standard C++ works). That's why there is new/delete which will call constructor and destructor.
Take a decent C/C++ book and read about object allocation.

Originally posted by ruben:
"In C++ code make sure that you override new/delete. It may be convenient to override in global scope instead of per class basis. If you are planning to use array new/delete for your class then make sure that you override vector new/delete, otherwise ARM compiler will complain."
Im trying to make an Array Class for BREW (C++) so porting from J2ME is easier.
I understand the concept of overriding the operators (mostly!) but what do you mean by "make sure that you override vector new/delete".
vector new/delete ?
Thanks.

Originally posted by ruben:
"In C++ code make sure that you override new/delete. It may be convenient to override in global scope instead of per class basis. If you are planning to use array new/delete for your class then make sure that you override vector new/delete, otherwise ARM compiler will complain."
Im trying to make an Array Class for BREW (C++) so porting from J2ME is easier.
I understand the concept of overriding the operators (mostly!) but what do you mean by "make sure that you override vector new/delete".
vector new/delete ?
Thanks.

new[] and delete[]

new[] and delete[]

But you are true, it depends on the application. On none of my games i needed some c++ functionalities, so i usually prefer fast games instead of "uml-compliant" applications! Btw, it was just an advice, everybody is smart enough to take his own choices.
/kUfa
My own experience is I have built an entire game development framework in C++ with all low-level graphics routines written in classes. In addition, I've written my own data structure templates to support Queues, stacks, Heaps, BS trees, etc. I've also build an entire Forms based GUI system with common controls and such, again all in C++. I do everything in C++.
Now, given that, I just finished recently a game, built on this entire framework, which does full screen 2D rendering horse racing (side view) with 8 (80x50 pixels each) horses running a fast moving track, with AI, mini map (for showing where you are on the track), etc. The track is 176x100 pixels, and there are furlong markers that are drawn on the track at appropriate times. In addition, I draw the stuff in layers, and I use painter's algorithm to do the z-ordering of the horses. So they draw correctly according to depth. I also do my own clipping in my sprite routines, as I decompress/draw.
On a VX7000 I get about 14fps. All of my sprites being displayed are my own sprite classes, with my own sprite format (NO BREW API). The sprites are compressed in memory by RLE and I decompress and draw them all on the fly with transparency. Horses, track, furlongs, minimap, interface, position markers, everything, every frame.
Again, everything being done in C++, no BREW API used for graphics, other than IDIB which I rending to the back buffer of the display, and I can still get 14fps on the phone. The game also doest HTTP communications to post high scores. Maybe, 14fps on the Vx7000 is bad and I just don't know it, but from my perspective, it looks great.
On top of all of that, my .MOD file is only 78K with over 30 classes in the project, many of which are game screens which subclass the my Form object.
Seems to me that C++ does just fine, and given the complexity of all the stuff I am doing, it's really a non issue in terms of performance, but it is a huge issue in that it gives me the greatest flexibility, allowing me to apply OO principles to maximize code reuse.
Sure, we can look at disassembly all day long and count assembly instructures, but it just isn't worth it. If I was worried about that, I would just write assembly language code. I give the ARM compiler much credit. It does a pretty darn good job creating lean code.
So I say, everyone should program in what they feel comfortable with.
It's not the journey that matters, but where you end up. It's just nice to know you have options :-)
:)

But you are true, it depends on the application. On none of my games i needed some c++ functionalities, so i usually prefer fast games instead of "uml-compliant" applications! Btw, it was just an advice, everybody is smart enough to take his own choices.
/kUfa
My own experience is I have built an entire game development framework in C++ with all low-level graphics routines written in classes. In addition, I've written my own data structure templates to support Queues, stacks, Heaps, BS trees, etc. I've also build an entire Forms based GUI system with common controls and such, again all in C++. I do everything in C++.
Now, given that, I just finished recently a game, built on this entire framework, which does full screen 2D rendering horse racing (side view) with 8 (80x50 pixels each) horses running a fast moving track, with AI, mini map (for showing where you are on the track), etc. The track is 176x100 pixels, and there are furlong markers that are drawn on the track at appropriate times. In addition, I draw the stuff in layers, and I use painter's algorithm to do the z-ordering of the horses. So they draw correctly according to depth. I also do my own clipping in my sprite routines, as I decompress/draw.
On a VX7000 I get about 14fps. All of my sprites being displayed are my own sprite classes, with my own sprite format (NO BREW API). The sprites are compressed in memory by RLE and I decompress and draw them all on the fly with transparency. Horses, track, furlongs, minimap, interface, position markers, everything, every frame.
Again, everything being done in C++, no BREW API used for graphics, other than IDIB which I rending to the back buffer of the display, and I can still get 14fps on the phone. The game also doest HTTP communications to post high scores. Maybe, 14fps on the Vx7000 is bad and I just don't know it, but from my perspective, it looks great.
On top of all of that, my .MOD file is only 78K with over 30 classes in the project, many of which are game screens which subclass the my Form object.
Seems to me that C++ does just fine, and given the complexity of all the stuff I am doing, it's really a non issue in terms of performance, but it is a huge issue in that it gives me the greatest flexibility, allowing me to apply OO principles to maximize code reuse.
Sure, we can look at disassembly all day long and count assembly instructures, but it just isn't worth it. If I was worried about that, I would just write assembly language code. I give the ARM compiler much credit. It does a pretty darn good job creating lean code.
So I say, everyone should program in what they feel comfortable with.
It's not the journey that matters, but where you end up. It's just nice to know you have options :-)
:)

Quote:mohlendo
new[] and delete[]
As suggested I have overloaded new[] and delete[] for my string class. But the device hangs when i try to use new[].
void* StringClass::operator new[](size_t size)
{
return MALLOC(size);

But when I write StringClass *str = new StringClass[2];
it resets the device. I tried creating a file in new operator to see where it is failing, but it is not even going inside new.
Simple object creation is working fine.
StringClass *str = new StringClass;

Quote:mohlendo
new[] and delete[]
As suggested I have overloaded new[] and delete[] for my string class. But the device hangs when i try to use new[].
void* StringClass::operator new[](size_t size)
{
return MALLOC(size);

But when I write StringClass *str = new StringClass[2];
it resets the device. I tried creating a file in new operator to see where it is failing, but it is not even going inside new.
Simple object creation is working fine.
StringClass *str = new StringClass;

Well, you're never calling operator new[](size_t) but you're calling operator new(size_t), that you havent redefined..

Well, you're never calling operator new[](size_t) but you're calling operator new(size_t), that you havent redefined..

Sorry, I have now edited the message. I forgot to add [2].

Sorry, I have now edited the message. I forgot to add [2].

You showed that you have a string class where you defined an operator new. However, you do not need to do that in your string class. What you need to do is overload the GLOBAL operator new.
I've had no trouble using new, delete, and delete[] operators on any products. Here is an example:
inline void* operator new(unsigned int size) {
return MALLOC(size);

inline void* operator new[](unsigned int size) {
return MALLOC(size);

inline void operator delete(void* ptr) {
FREE(ptr);

inline void operator delete[](void* ptr) {
FREE(ptr);

Do something like this and you will overload the global new and delete operators. Include this file where ever you use new and delete.

You showed that you have a string class where you defined an operator new. However, you do not need to do that in your string class. What you need to do is overload the GLOBAL operator new.
I've had no trouble using new, delete, and delete[] operators on any products. Here is an example:
inline void* operator new(unsigned int size) {
return MALLOC(size);

inline void* operator new[](unsigned int size) {
return MALLOC(size);

inline void operator delete(void* ptr) {
FREE(ptr);

inline void operator delete[](void* ptr) {
FREE(ptr);

Do something like this and you will overload the global new and delete operators. Include this file where ever you use new and delete.

I have overloaded new/delete and new[]/delete[] globally also. But still new[] is not working.
Have you tried creating an array of object of your class.
I have posted my verbose output in another thread. Here's the link.
http://brewforums.qualcomm.com/showthread.php?t=9970
Some vector.o member is loaded when we use new[].

I have overloaded new/delete and new[]/delete[] globally also. But still new[] is not working.
Have you tried creating an array of object of your class.
I have posted my verbose output in another thread. Here's the link.
http://brewforums.qualcomm.com/showthread.php?t=9970
Some vector.o member is loaded when we use new[].

For those who want to program in C++, be careful when declaring instance objects in your Applet structure. The AEEApplet_New does not create the memory for the applet object by using new, but rather a traditional malloc. This means that your constructors and destructors will not be called implicitly. You will have to do that explicitly yourself. I suggest putting all of your data in another class and instantiating it with a new after creating your applet object. Then when you free your app data, you can delete it.
class MyData {
String name; // String class which has default constructor
Object a; // Some class which has a default construtor
int32 score; // Just some regular type data
}
class MyApplet {
AEEApplet applet;
MyData* pData;
};
// Initialization
MyApplet* pApp;
AEEApplet_New(...., &pApp, .....); //Create the main applet structure
pApp->pData = new MyData;
...
...
//Free App Data
delete pApp->pData;
This is a really rough sample, but it gets the point across.

For those who want to program in C++, be careful when declaring instance objects in your Applet structure. The AEEApplet_New does not create the memory for the applet object by using new, but rather a traditional malloc. This means that your constructors and destructors will not be called implicitly. You will have to do that explicitly yourself. I suggest putting all of your data in another class and instantiating it with a new after creating your applet object. Then when you free your app data, you can delete it.
class MyData {
String name; // String class which has default constructor
Object a; // Some class which has a default construtor
int32 score; // Just some regular type data
}
class MyApplet {
AEEApplet applet;
MyData* pData;
};
// Initialization
MyApplet* pApp;
AEEApplet_New(...., &pApp, .....); //Create the main applet structure
pApp->pData = new MyData;
...
...
//Free App Data
delete pApp->pData;
This is a really rough sample, but it gets the point across.

kUfa wrote:Well, as far I know arm C++ does not support exception handling.. Then it totally depends on the way you prefer to implement errors; ususally what i do is to have a int8 return value in all my "critical" functions, ie all of them that alloc mem / access files /etc.. So basically if there is an error somewhere, it will give it to all the calling functions, which can handle it.. Btw sorry if my english is not that good hehe
:D
C++ supports exception handling. However, for embedded devices the overhead of using exception mechanism might be very resource consuming

kUfa wrote:Well, as far I know arm C++ does not support exception handling.. Then it totally depends on the way you prefer to implement errors; ususally what i do is to have a int8 return value in all my "critical" functions, ie all of them that alloc mem / access files /etc.. So basically if there is an error somewhere, it will give it to all the calling functions, which can handle it.. Btw sorry if my english is not that good hehe
:D
C++ supports exception handling. However, for embedded devices the overhead of using exception mechanism might be very resource consuming

Hi j0rd,
i am using ISHELL_PostEventEx in a diferent way.
I am doing in the way mentioned below.
i am posting events to my own applet & suddenly the END key is pressed.
My QUESTION is : If the brew is having any pending events which we have posted and if it is getting the END key, what is the order of dispaching the events into my aplet.
i also want to know, if it has some pending events for an applet in the BREW, and if it has dispatched EVT_APP_STOP, and if the applet is unloaded, whether it will be loaded again & send the remaining pending events ?
Regards
Justin.

Hi j0rd,
i am using ISHELL_PostEventEx in a diferent way.
I am doing in the way mentioned below.
i am posting events to my own applet & suddenly the END key is pressed.
My QUESTION is : If the brew is having any pending events which we have posted and if it is getting the END key, what is the order of dispaching the events into my aplet.
i also want to know, if it has some pending events for an applet in the BREW, and if it has dispatched EVT_APP_STOP, and if the applet is unloaded, whether it will be loaded again & send the remaining pending events ?
Regards
Justin.

brewee wrote:C++ supports exception handling. However, for embedded devices the overhead of using exception mechanism might be very resource consuming
Hi Brewee,
Although C++ supports Exception handling, but in case of Brew, it isn't supported. ARM compilation will shower some errors....
SoftEast

brewee wrote:C++ supports exception handling. However, for embedded devices the overhead of using exception mechanism might be very resource consuming
Hi Brewee,
Although C++ supports Exception handling, but in case of Brew, it isn't supported. ARM compilation will shower some errors....
SoftEast

come to top!!! :D

come to top!!! :D