03 Feb 2012 14:28 - by Boris Gulay
I believe that my experience in porting library to new platform will be useful to all who want to do the same for another platforms. Especially because Windows Mobile is very limited in support of standard C library and STL features.
List of problems
To all who don't want to read the whole article.
- Needs special preprocessor directives to compile.
- UUID generation.
- Does not support some standard library routines (threading, file operations).
- Does not support some socket options.
- Some include files have different names.
- Many include files are missing.
- Missing of ANSI library and API functions.
To get started
I made a port on the basis of existing project for MSVC. It is very easy: you just need to add new platform to the project. I've added Windows Mobile 5 because I have SDK installed. Right after adding new platform you can switch to it and press compile button. After compile process stops you will find many errors in the output window. Let's start fixing it.
If you compile just after adding new platform you will receive a lot of errors with undefined symbols. It's because building for WM requires special symbols to be defined.
I pick them from new WM project. So, here they are:
Variables references in this defines are set inside WM SDK.
To use unicode versions of WinAPI functions (because ANSI are not avaliable on WinCE) you need to add two additional definitions:
This will switch all WinAPI to unicode. By the way be careful with string arguments you pass to that functions.
Windows code uses UuidCreate function to generate GUIDs and UuidToString to convert it to string representation. This functions live in special RPC library (I mean separate DLL file).
Problem is that WM does not have this library. I've checked not only emulator but also all real devices I have: nothing. Even if you can compile the code (by manually including required header) you build will fail on the linker step.
After short googling and searching over MSDN I found that WM supports another function to generate GUIDs: CoCreateGuid. It also has a function to convert it to string, but as all WM API it produces unicode string.
So my solution was to use CoCreateGuid to generate unique IDs and snprintf (from code for other platforms) to convert it to ANSI string.
I was afraid that CoCreateGuid may require call to CoInitialize to work properly but fortunately it does not.
By the way I have to change class member type to char array because UuidToString allocates memory itself but snprintf requires already allocated buffer.
Missing C library routines
Yes, some functions from C library, available on desktop windows, are missing on WM.
- Can be easily changed to CreateThread (function from WINAPI with the same signature). Signature of thread procedure should also be changed. (stdcall calling convention is not supported on WM).
- I found no acceptable replacement. So just excluded call to this function when compiling for WM with include directive for stat.h (it's also missing). That's why swap directory is not checked to be writeable on Windows Mobile.
- close, unlink, open, lseek
- Can be replaced with WINAPI calls (standard library headers are missing). Some type casts will be required and all string arguments must be in unicode (see below).
Missing socket option
Option SO_EXCLUSIVEADDRUSE (and SO_REUSEADDR) is not supported. So I just excluded call to setsockopt with #ifdef.
Different names of some include files
Fortunately there was only one such file: intrin.h. In WM it's name is cmnintrin.h. I'm not sure is content of this file actually used or not, because VS shows me that code in this file is not available because of missing precompiler directive.
Missing include files
Most of missing files are mentioned above:
But the main trouble is with missing errno.h. Global errno variable is actively used by the library so I have to find some way to bring errno back to WM.
After some investigation I've found that library use errno just to pass results of one function call to another. The code does not analyse values returned from system calls. This gives me an idea to just add errno.h from standard library directly to the project.
I've found sources and add two files to the project: errno.hpp (with status code definitions and global variable declarations) and errno.cpp (with variable definitions). I also have to add strerror function (I've implemented it with FormatMessage call).
Missing ANSI functions
Windows Mobile is totally Unicode. It has no ANSI function equivalents like desktop windows has. But the worst thing is that it has no ANSI functions in standard library too.
Fortunately there are only few places inside the library where strings are used.
- uuid_t (to convert GUID to string)
- _snprintf function is available in ANSI version.
- swap (file names)
- All API file functions require Unicode string. But file names are generated inside the class so I've just replace std::string to std::wstring and it works.
- error messages
- I found no good way to change it all to Unicode not to convert Unicode string to ANSI. So I just make it return wchat_t string inside char (by casting pointers). Hope errors will happen not so often.
clrzmq (.NET wrapper)
I also make clrzmq compile for WM. There is not so many changes in it so I will not mention it here.
If you will find it interesting you can ask me to write another article about porting clrzmq on Windows Mobile. :)