Contents > Porting PocketC Applications

Porting PocketC Applications

General Approach The basics of to porting to PocketC Architect.
Breaking Changes Breaking changes and common porting errors.
API Conversion Notes Additional notes on converting from old APIs to new.
Legacy API Reference for legacy PocketC APIs.

Contents > Porting PocketC Applications > General Approach

General Approach

Porting an application from PocketC to PocketC Architect is generally simple, and can be done in several phases. You can get your application running by only performing the first porting phase. To take full advantage of the new features and improved performance of the OrbC runtime, you may need to do a full conversion, as described below.

Phase 1: Compiling a Legacy PocketC Application

The first and easiest step is simply getting your application to compile. The PocketC Architect requires you to specify a few properties of the application in an @app block. The only required @app properties are creator, name, and dbname. For example:

@app {
  creator = "MyAp"; // same as PocketC's @cid
  name = "App Name"; // display name, same as PocketC's @name
  dbname = "AppName-MyAp"; // name of .prc database, same as PocketC's @dbname
}

Second, you must include the PocketC compatibility headers. The OrbC runtime has a richer, object-oriented API, and doesn't support the PocketC APIs by default. In order to use the PocketC APIs, you must include the appropriate header files which implement the APIs you intend to use. The easiest way to start is to just include "pc_most.oc", which contains all of the PocketC APIs except those that require native add-ins. This is sufficient for most applications.

#include "pc_most.oc"

The following table lists all the compatibility headers:

pc_most.oc Includes all headers except those that would require a native add-in to be installed. Most applications should just use this header.
pc_all.oc Includes all headers.
pc_io.oc Implements the Basic I/O functions (e.g. puts, gets, clear).
pc_events.oc Implements the event functions (e.g. pcevent, key, wait).
pc_string.oc Implements the string functions (e.g. strlwr, strtok).
pc_math.oc Implements the mathlib function.
pc_graphics.oc Implements the graphics functionns (e.g. graph_on, rect, bucreate).
pc_sound.oc Implements getvol.
pc_date.oc Implements the time and date functions (e.g. time, date).
pc_database.oc Implements the database functions (e.g. dbopen, dbcreate).
pc_memo.oc Implements the memo functions (e.g. mmnew).
pc_serial.oc Implements the serial port functions (e.g. seropenx). OrbSerial native add-in is required if this header is included. This header is not included by pc_most.oc.
pc_system.oc Implements the system functions (e.g. clipget, getsysval).
pc_memory.oc Implements the memory functions.
pc_network.oc Implements the network functions (e.g. netopen, sockopen). OrbNetwork native add-in is required if this header is included. This header is not included by pc_most.oc.
pc_vfs.oc Implements the VFS functions (e.g. fileread, filewrite). OrbVFS native add-in is required if this header is included. This header is not included by pc_most.oc.

Once the correct headers are included, there are three primary changes that must be made because of conflicts between the OrbC runtime and PocketC.

Phase 2: Convert to the New UI, Eventing, and Drawing Model

Using the new UI and eventing model makes programming new application much easier, and provides many benefits for existing applications. The most important benefit is that the new UI model uses native forms and controls, making applications much faster and more responsive to users. Another notable benefit is that forms and controls using the new UI model can automatically resize on devices with wide/tall screens without writing any code.

The new UI model, eventing model, and drawing model are not compatible with the old models. If you convert one of your forms from e.g. CControls, you must convert all of your forms, use only the new eventing model (no more pcevent(), key(), or similar calls), and use only the Draw methods (Draw.rect() instead of the rect() function). The reverse is also true, you cannot use the new eventing model if you are using the old graphics APIs (such as graph_on).

This phase is optional and straightforward, but may take considerable time. There are three basic steps involved:

Phase 3: Convert to the Object-Oriented APIs

Finally, you can convert from the old PocketC APIs to the new object-oriented APIs. In many cases, the old APIs implemented in the PocketC compatibility headers are just thin wrappers around the new APIs. There are two primary advantages to using the new APIs:


Contents > Porting PocketC Applications > Breaking Changes

Breaking Changes

Legacy PocketC applications can be compiled with PocketC Architect with very few changes. This page lists the changes in the compiler and runtime that are incompatible with legacy PocketC applications. At the bottom of the page is a short list of the most common compiler errors during the porting process, and how to fix them.

Deprecated Functions

The following functions are no longer supported:

Changed Functions

The following functions have changed either their signatures or behaviors:

All or Nothing Conversions

Native Libraries

Any new native code should be written as an OrbC native add-in. However, native libraries are supported with a few limitations:

For native library developers, do the following things to ensure that your library runs correctly:

Other Issues/Differences

Common Compiler Errors

In porting your legacy PocketC application to OrbC, there are several common errors you may encounter:


Contents > Porting PocketC Applications > API Conversion Notes

API Conversion Notes

Much of the legacy PocketC APIs maps easily to the new object-oriented APIs. However, it may be helpful to cover a few specific categories.

Graphics

In legacy PocketC, graphics were created by drawing directly to the screen, generally after opening the graphics form by calling graph_on(). Although easy to use, this mechanism results in global graphics state that doesn't fit nicely in a structured application, and doesn't work well with gadgets. The approach taken in OrbC is to draw using a Draw object. A Draw object is used to draw to either a form, a gadget, or an offscreen buffer. Drawing to a Draw object must be done between calls to begin and end.

Events

The eventing model in OrbC is substantially different that legacy PocketC. The most important difference is that your application doesn't have an event loop at all. Instead, you implement handlers for form and control events.

Database

The legacy PocketC functions always operated on the current database and record. In OrbC, multiple databases and records can be opened at once.


Contents > Porting PocketC Applications > Legacy API

Legacy API

Library Routines

Built-in Functions

Basic I/O

Event System

String

Math

Note: Functions that require MathLib will display an error if the library is not present.

Graphics

Color Tables

Sound

Time/Date

Database I/O

All the database functions work on databases with any creator id/type, but use of resource databases may cause unexpected results. When creating a new database, the database will have creator id 'PktC' and type 'user'. An attempt to overwrite a database with a given name but different creator/type will fail. Only one database can be open at a time.

Memo Pad I/O

Serial I/O

System

Memory Management

A few notes that will help understand the following section: In a normal computer, memory is divided into bytes and words. PocketC divides its memory into elements called "values". Each value stores a basic PocketC type (int, char, float, string, pointer). Also, each element of memory knows its own type (thus the need for the settype() function).

Networking

PocketC's networking support is based on BSD-style sockets. This documentation assumes you understand the functionality and is not intended to teach you to use BSD-style sockets. Currently only TCP sockets are supported. Almost all of the networking functions returns 0 on success and an error code on failure. To interpret the error code, you can call the neterror() function provided in neterror.h (in PocketC's UtilCode directory) which will convert the error code to a string.

All the functions that take and return addresses use a string representation. An address string is a dotted IP address with optional port, such as: "129.22.104.22:80" An empty string is interpreted as the local address. Thus, when calling sockbind(), only a port needs to be specified: ":1234". All socket methods (and the DNS methods) have a timeout associated with them. This timeout value is globally set using netsettimeout().

VFS

The Palm OS support for Virtual File Systems (VFS) allows an application to read and write files to removable storage, such as a compact flash card or memory stick. Almost all of the VFS functions returns 0 on success and an error code on failure. To interpret the error code, you can call the vfserror() function provided in vfserror.h (in PocketC's UtilCode directory) which will convert the error code to a string. This file also contains #defines for many useful VFS constants. Some methods do not work as documented on the emulator (attributes and dates will be incorrect).

To access a file, you must first retrieve the volume on which it resides using enumvols(). This function will enumerate all volumes on the device - if the device does not support VFS, no volumes will be returned. Once you have retrieved the volume id, you can use it to create and open files and directories. To get a list of all the files in a directory, first open the directory with volopendir(), then enumerate through the files and directories using direnum(). The get the files in the root directory, call direnm(dirid, "/"). Unlike traditional operating systems, the Palm OS VFS support does not support a concept of "current directory". Instead, all paths are fully specified for a given volume.