Creating native libraries allows a PocketC developer to write code that executes faster than similar PocketC code. It also allows a user to expose functionality to a PocketC applet that PocketC's built-in library does not provide. Such libraries can be released for use by other developers, which helps the PocketC and Palm community.
This document does not cover aspects of PalmOS system libraries. In theory, all that you need to know about system libraries to create a PocketC native library is either included in the document, or is already written in the sample library. For more information, check the PalmOS SDK.
Assuming you have a copy of Codewarrior installed, creating native libraries is almost trivial. Users who wish to use other tools, such as GCC, will need to do a little more work. At this time, OrbWorks will provide no support for GCC developers since we have not used or tested it. (If anyone is able to compile the sample with GCC, let us know so that we can help others).
A value is the C++ datatype that represents all PocketC datatypes in the form of a union. A value has a type field, which describes the type of the value. Only one of the other fields is used (based on the type). A type can be one of vtInt, vtFloat, vtChar, or vtString.
Important: A string is stored somewhere in dynamic memory, and a value holds a handle to it, not a pointer. Once a value containing a string is no longer needed, it must be deleted using the cleanup() function.
A function declaration (created with a call to addFunc() ) consists of a name, a number of arguments, and a list of up to ten argument types. The arguments may be one of the standard types or can be of type vmVoid. A parameter of type vmVoid means that the compiler will not cast the parameter that is passed. In other words, the user can pass in any type of value, and no conversion is automatically performed.
PocketC pushes all parameters on the the stack in the order they appear in the function declaration. So, a function declared with two parameters [func(int x, int y)] will have the x pushed on the stack first, followed by the y. Therefore, the first value popped off the stack will be the y.
A function set the return value by setting the global variable retVal. When PocketC calls the library, the return value is set to type=vtInt, vtInt=0.
The C++ function that implements your PocketC library function will take only one parameter, a pointer to the global data. It will obtain the PocketC parameters by using the pop() function and will call cleanup() on all string parameters.
This function is called both at compile and run time. This function should set up your globals and return a pointer to you locked globals. The function pointers in the global structure are filled in after this call, so they are not yet available.
This function is called both at compile and run time. This function should free the global structure.
This function is called only at compile time. This function should add function prototypes by calling addFunc(). The first function added is given an index of 0.
This function is called only at runtime. The function should contain a switch statement which calls your C++ functions to process the PocketC function call. The index of the functions must match the order in which they were added in PocketCLibAddFunctions().
pops a value off the stack. If it is a string value, you must call cleanup() on it when you are finished using it.
pushes a value on the stack. The value is copied to the stack. If it is a string, the string is also copied, so you must call cleanup() on the original value after you push it on the stack.
Frees the memory held by a string value. If the value is not a string, no processing is done. (i.e. it is always safe to call cleanup(), even when not needed).
Casts a value to the given type. If the new value is a string, it must be freed when no longer needed. If the original value is a string which is converted to another type, the string is freed automatically.
Casts both values to a matching type. For example, when this function is called with a float and an int, the int is cast to a float. If one is a string, the other is cast to a string.
Allows the system to process PalmOS events. This function also sets up the return values for the PocketC event() function and processing PalmOS events on behalf of PocketC. You must call this if your operation will take a while. If the blocking parameter is true, a single PalmOS event will be processed. If none are available, the system will wait for one. If blocking is false, the system will process all waiting messages and return.
Calls the PocketC function at address location. Before this call, you must push the parameters on the stack (in the order of the function's parameter list). You can obtain the address of a function by accessing it in your PocketC source code without parentheses. (e.g. puts(main); will print the address of the function main). This function cannot be used to call PocketC's built in functions. Calling this function recursively is not very smart.
Important: The function's return value is placed on the stack. You must pop it off the stack after it has been called. A call to this function will modify retVal
To use a native library in a PocketC applet, you must instruct the compiler to load the library's functions. This is done through the library keyword.
Example:
// My Applet library "PocketCLib" main() { int x; x = times5(7); }
The name of a library function cannot be the same as a user function. However, it may be the same as the name of a builtin function. In this case, the compiler will generate calls to the native library function rather than the builtin function.