Anal Suggestions on C++ Use | developer.brewmp.com Anal Suggestions on C++ Use | developer.brewmp.com

Developer

Anal Suggestions on C++ Use

Forums:

Hi,

Was wondering if Qualcomm had any suggestions on best practices when programming in C++ on a Qualcomm\BREW chipset. I know that 'just use C' is the optimal approach, but let's put that one aside for now.

I know the basics - the main one being, don't make your inheritance levels too deep, and keep the number of classes down.

What about the entry point of the applet. Traditionally, I see developers wrapping the BREW implementation class or set of C functions around some 'GameEngine' controller class, which handles semi platform-independent game logic. What if the base controller class IS the BREW applet. Does that make any difference in terms of performance? is there any point in thinking about this?

Any suggestions, and perhaps a highly optimized sample app would greatly be appreciated. I think a lot of people could benefit from this.

I think whether you write C++ code for BREW programming or any other platform, the basic suggestions are same.
Inheritance depth is one example you already stated. Other similar quick suggestions are:
-- Un-necessary use of virtual functions (remember that a virtual function call takes a coupla or so more ARM instructions for call-dispatch than a normal C++ call; also there is a cost of 4 bytes (or 2 on thumb) associated per object, not to mention the space taken by virtual table)
-- Making a virtual function as inline(this causes compiler to create out-of-line copy of the inlined function thus leading to code bloat)
-- Being aware of copy-constructors (I saw very ugly C++ code this morning on this forum. Something like this:
Foo f = Foo();
f.SomeMethod();
Here, the compiler will have to generate 2 calls to constructors: once for default constructor and then for copy c'tor:
Foo temp; //invoke default c'tor on temp obj...
Foo f(temp); //...and then call state of temp into f
-- Being aware of when would compiler call a conversion constructor
-- Un-necessary use of virtual inheritance
-- Un-necessary use of templates (template causes code bloat like hell)
There are many such guidlines that one must be aware of when writing C++ code.
-Viren

I think whether you write C++ code for BREW programming or any other platform, the basic suggestions are same.
Inheritance depth is one example you already stated. Other similar quick suggestions are:
-- Un-necessary use of virtual functions (remember that a virtual function call takes a coupla or so more ARM instructions for call-dispatch than a normal C++ call; also there is a cost of 4 bytes (or 2 on thumb) associated per object, not to mention the space taken by virtual table)
-- Making a virtual function as inline(this causes compiler to create out-of-line copy of the inlined function thus leading to code bloat)
-- Being aware of copy-constructors (I saw very ugly C++ code this morning on this forum. Something like this:
Foo f = Foo();
f.SomeMethod();
Here, the compiler will have to generate 2 calls to constructors: once for default constructor and then for copy c'tor:
Foo temp; //invoke default c'tor on temp obj...
Foo f(temp); //...and then call state of temp into f
-- Being aware of when would compiler call a conversion constructor
-- Un-necessary use of virtual inheritance
-- Un-necessary use of templates (template causes code bloat like hell)
There are many such guidlines that one must be aware of when writing C++ code.
-Viren

In BREW C++ works just fine as any other environment. I agree with most of the points that are mentioned by "drvirens". I guess the information you are seeking for is how to write C++ for embedded systems. There are quite a few web resources on best practices for embedded system programming using C++ (more accurately embedded C++).

In BREW C++ works just fine as any other environment. I agree with most of the points that are mentioned by "drvirens". I guess the information you are seeking for is how to write C++ for embedded systems. There are quite a few web resources on best practices for embedded system programming using C++ (more accurately embedded C++).

-- Being aware of copy-constructors (I saw very ugly C++ code this morning on this forum. Something like this:
Foo f = Foo();
f.SomeMethod();
Here, the compiler will have to generate 2 calls to constructors: once for default constructor and then for copy c'tor:
Foo temp; //invoke default c'tor on temp obj...
Foo f(temp); //...and then call state of temp into f
One of the methodoloy I personally follow is the, if the class is not meant for assignment/copy, I make them as private with empty body, so that team members modifying the code at later point of time can't do any assignment accidentally.

-- Being aware of copy-constructors (I saw very ugly C++ code this morning on this forum. Something like this:
Foo f = Foo();
f.SomeMethod();
Here, the compiler will have to generate 2 calls to constructors: once for default constructor and then for copy c'tor:
Foo temp; //invoke default c'tor on temp obj...
Foo f(temp); //...and then call state of temp into f
One of the methodoloy I personally follow is the, if the class is not meant for assignment/copy, I make them as private with empty body, so that team members modifying the code at later point of time can't do any assignment accidentally.

> if the class is not meant for assignment/copy, I make them as private with empty body,
If the class is NOT meant for assignment or copyable, then I dont even provide the "empty" body. I rather have linker report me that an assignment or copy has been for objects not meant for so.
REMEMBER: Try to write code that would result:
-- compiler surfacing certain un-required defects rather than writing code that would allow errors getting thru' linking/run-time stage.
-- linker surfacing the errors rather than defects making their way into final exe image (at run-time)
The rule of thumb: AFAP, try to get rid of errors at an early stage of development. (We all know how expensive it becomes when bugs make their ways into developed software).
I wish I could write the above description in a more understandable way!!
-Viren

> if the class is not meant for assignment/copy, I make them as private with empty body,
If the class is NOT meant for assignment or copyable, then I dont even provide the "empty" body. I rather have linker report me that an assignment or copy has been for objects not meant for so.
REMEMBER: Try to write code that would result:
-- compiler surfacing certain un-required defects rather than writing code that would allow errors getting thru' linking/run-time stage.
-- linker surfacing the errors rather than defects making their way into final exe image (at run-time)
The rule of thumb: AFAP, try to get rid of errors at an early stage of development. (We all know how expensive it becomes when bugs make their ways into developed software).
I wish I could write the above description in a more understandable way!!
-Viren

Just to add my two cents, with something obvious... ;)
If you have a really good design BEFORE start coding, performance will be somehow equivalent either in C or C++. If you have a poorly designed app, with a bad implementation, well... the language won't save you.. :)
Also, the reason of wrapping C calls to C++ class is that the callbacks and main applet structure come from BREW / C. You can register these callbacks as methods from your class, but they'll need to be "static", and then you'll probably want to dispatch them to your actual object method...
So I guess there won't be too much of a difference wrapping C to C++, or static C++ method to a regular object method.

Just to add my two cents, with something obvious... ;)
If you have a really good design BEFORE start coding, performance will be somehow equivalent either in C or C++. If you have a poorly designed app, with a bad implementation, well... the language won't save you.. :)
Also, the reason of wrapping C calls to C++ class is that the callbacks and main applet structure come from BREW / C. You can register these callbacks as methods from your class, but they'll need to be "static", and then you'll probably want to dispatch them to your actual object method...
So I guess there won't be too much of a difference wrapping C to C++, or static C++ method to a regular object method.

> but they'll need to be "static"
Yes, but at the cost of compiler compatibility. :-) I mean, unless you wont be compiling your C code and C++ code with same compiler, there _MAY_ be the problems in calling caonventions aspect. Although in practise, most compiler vendors implement them to be compatible.
The best thing, in my view, is to keep the callback as extern "C", and then in its implementation, use C++ virtual fucntion calls to dispatch calls based on type of the objects. (May not be always needed).
-Viren

> but they'll need to be "static"
Yes, but at the cost of compiler compatibility. :-) I mean, unless you wont be compiling your C code and C++ code with same compiler, there _MAY_ be the problems in calling caonventions aspect. Although in practise, most compiler vendors implement them to be compatible.
The best thing, in my view, is to keep the callback as extern "C", and then in its implementation, use C++ virtual fucntion calls to dispatch calls based on type of the objects. (May not be always needed).
-Viren

Great replies! Thanks guys!
I'm very interested in how most of you are implementing your base game calsses in BREW. Are you using static C callback functions which proxy to your game controller class, or are you having that class inherrit AEEApp (I think I've seen this) - having the class handle BREW callbacks it registers for?

Great replies! Thanks guys!
I'm very interested in how most of you are implementing your base game calsses in BREW. Are you using static C callback functions which proxy to your game controller class, or are you having that class inherrit AEEApp (I think I've seen this) - having the class handle BREW callbacks it registers for?

i dont write game software so i guess i am outta this. :-)

i dont write game software so i guess i am outta this. :-)