10 July 2004
Windows CE development
This entry is a repository for tips and resources on writing C++ code for Windows CE. I'll be continually updating it and reorganizing it as I find new information.
- Windows CE and Pocket PC: FAQ (Microsoft, 2001)
- Using std::map<>
- Exception handling and RTTI
- _com_ptr_t, _bstr_t, _com_error, and RTTI
- Crashes with an invalid stack or a corrupt this
The moniker "Pocket PC" is used to denote the OS and all applications included in a PDA. Different OEMs have different, customized versions of Pocket PC.
"Windows CE" denotes the development components used to build specific versions of the Pocket PC OS.
I've read this FAQ several times and it continues to baffle me why they didn't use clearer names. I'm still not confident, based on their use in articles, when one term or the other is appropriate.
These two threads discuss resolution of the issue:
Google Groups: View Thread "error LNK2019 unresolved external symbol public _..."
Google Groups: View Thread "How to use map in eVC++ 4.0"
The posters say that the std::_Lockit implementation is flawed on CE. The desktop source is in xlock.cpp and can be copied to yvals.h for CE. I avoid at all cost altering platform source. My alternate solution is to #undef _MT before I #include <map>. We'll see whether that bites me in the ass later on.
And this thread discusses it further and includes a _Lockit implementation. I didn't try very hard, but I couldn't eliminate the linker errors using that code.
Google Groups: View Thread "Try-catch support in an ATL COM developed with eVC 4..."
Google Groups: View Thread "C++ exceptions with Pocket PC 2003"
Exception handling is supported, but RTTI is not. You have to be cautious about what functions you call (some throw-ing objects and expecting the missing parts of RTTI). For example, you can't call std::vector<>::at(size_type pos) because it will throw (and is one of the very few stl methods that does) on out of range. std::bitset<> throws exceptions for most of its accessor functions.
Here are some detailed articles on both:
C++ Reference Guide: Exception Handling
How a C++ compiler implements exception handling (very detailed, low-level)
The COM helper classes are missing some of their conversion and RTTI code. Smart pointers based on _com_ptr_t will throw _com_error. I created a dummy implementation of type_info to resolve the linker issues with this:
class type_info { public: virtual ~type_info() {} int operator==(const type_info& rhs) const {return 1;} int operator!=(const type_info& rhs) const {return 0;} int before(const type_info& rhs) const {return 0;} const char* name() const {return "";} const char* raw_name() const {return "";} private: void *_m_data; char _m_d_name[1]; type_info(const type_info& rhs); type_info& operator=(const type_info& rhs); };
Although it should definitely be more robust, it serve the immediate purpose.
_com_error is forward-declared in comutil.h, but its definition is missing. You can get it from the desktop's comdef.h file, or create a dummy implementation. _bstr_t requires it and the following function also found in comdef.h:
inline void _com_issue_error(HRESULT hr) {throw _com_error();}
Finally, _bstr_t must be able to convert itself to other forms. These conversion functions are missing:
namespace _com_util { // Convert char * to BSTR // inline BSTR __stdcall ConvertStringToBSTR(const char* pSrc) { USES_CONVERSION; return A2BSTR(pSrc); } // Convert BSTR to char * // inline char* __stdcall ConvertBSTRToString(BSTR pSrc) { USES_CONVERSION; char * temp = W2A(pSrc); char * convert = new char[strlen(temp) + 1]; strcpy(convert, temp); return convert; } };
Remember when you ported your code from Windows 95 to Windows NT? Remember how all of that perfect code started crashing in unusual places? Well, get ready for more of the same. Just as 95 was more forgiving than NT, Windows 2000 and its ilk are more forgiving than CE. Expect your perfect code to show its true colors.
These errors will usually appear down-the-road, after the corruption happened. Once the crash happens, try walking into the code from a few function calls back. If you eventually jump into a non-related section of code before it crashes, you have some type of memory corruption (obviously). Check all of your string manipulation and especially your object contruction. Look for implicit copy contructors or assignment operators that copy incorrectly.
Also, be smart about memory management. Avoid using new and delete in the raw.
- Techniques after using Swift for a month posted by sstrader on 26 August 2015 at 11:41:51 PM
- Some thoughts on Ruby after finishing a week (minus one day) of training posted by sstrader on 15 December 2011 at 8:59:30 PM
- Links on the singleton pattern posted by sstrader on 9 December 2011 at 9:19:50 AM
- Phonebot posted by sstrader on 29 October 2011 at 6:37:05 PM
- The labeled break in Java posted by sstrader on 4 September 2011 at 11:27:56 AM