Creating new projects in Carbide

Creating a new project in Carbide C++ v1.3 entails a journey through several dialog boxes, one of which requests the name for the new project and a directory in which to put it. Carbide’s default location has a tendency to generate an error to the tune of “C:\Symbian\Carbide\Workspace is not a valid location”, even though the greyed-out default location shows, e.g., “C:\Symbian\Carbide\Workspace\MyNewProj”. I work around this by unchecking the “use default location” box and creating MyNewProj manually.

Symbian: RSocket::Recv and HBufC8

A common way to do stream-based network communication in Symbian OS is with the RSocket class. The RSocket::Recv(TDes8 &aDesc, …) method “only completes when the full amount of requested data has been received (or the connection breaks). This means when the descriptor has been filled to its maximum length (not its current length).”

This is handy if an application receives messages of unknown length, but those messages include a header that includes the length. E.g., always receive 4 bytes of header which encode the amount of payload data. What seems like a sensible thing to do is dynamically allocate a buffer descriptor to hold exactly the expected payload size. This seems nice because then the OS worries about reassembling fragmented or long messages.

Unfortunately, note that the heap descriptor of choice, HBufC8, when allocated with HBufC8::NewL(TInt aMaxLength), may not be the expected size: “Note that the resulting heap cell size and, therefore, the resulting maximum length of the descriptor may be larger than requested.” This is a problem, because it causes RSocket::Recv() to hang waiting for more data than the remote end has sent.

I’m aware of three work-arounds, and zero elegant solutions:

  • RSocket::RecvOneOrMore and manage buffers ourselves (more work: yuck).
  • Allocate a C-style array and don’t use Symbian descriptors. This page talks about that solution.
  • Cast the const pointer available for an HBufC8 and create a Tptr8 manually, assigning its max size to be precisely the message size. This page talks about that solution.

Currently I’m using the cast-away-the-const solution. Note that the HBufC8’s length will not be modified, so it must be set manually:

HBufC8 *iBuffer;
TPtr8 iBufferPtr;
...
iBufferPtr.SetLength(payloadSize); // without this iBuffer's length remains 0
iBufferPtr.Set((TUint8*)iBuffer->Des().Ptr(), 0, payloadSize);

My understanding is that SetLength() sets the current length of iBuffer. Set() sets the current length and maxlength of the TPtr8 object. Thus, RSocket sees the current length of 0 and max length of payloadSize, and behaves as expected. Code processing the iBuffer in some class’s RunL() will see the length that was set with SetLength(), but since RSocket is no longer operating with a mistaken notion of the desired amount of data to read, RunL() will only be called when the right amount of data has arrived.

It’s too late and I’m too tired to make this more concise. Forgive me.

UPDATE: It seems that an RBuf8 will solve this problem elegantly, but I haven’t had time to try it yet.

Parallels Reverse Transporter (Virtual to Physical)

Parallels for Max OS X allows me to run Windows XP in a virtual machine. Boot Camp allows native installation of Windows XP on Intel Macs. Parallels Transporter enables a Boot Camp-based native installation of Windows XP to run in a virtual machine while OS X is running, while simultaneously allowing the system to reboot and run Windows XP natively for extra graphics, performance, etc. Unfortunately, it’s designed assuming the native install of Windows XP was there first. In my case, I have a Windows XP virtual machine, and I would like the option to also boot it natively using Boot Camp. My best Google skills turned up this Virtual to Physical (Boot Camp) Guide, which is sufficiently involved that I haven’t tried it yet, but I will. Regardless, this virtual-to-physical transition is clearly something people want, and it’s only a matter of time. 🙂