Author: Scott Gruby, Palm OS Certified Developer
Why do I want to consider this problem?
As a person who has been engaged in Palm OS, I have witnessed the maturity and development technology of Palm OS. A few years ago, developers were very concerned about the problem of memory space (stack space), so they should write small and compact code as much as possible. With the increase in the application of the application, memory is not the most worryable problem of developers. A few years ago, when MetrowERKS began to allow developers to use C programming (there are some restrictions), some developers, including my own, don't use it due to "code expansion". At that time, due to the limited spaced space on the equipment, some people considered that the value of object-oriented / C programming was not enough to offset it. I saw a lot of debate about C and C , I think C increased overhead. And in my opinion, C will increase overhead is just a problem.
Since then, things have changed very much. The new device has a lot of memory, which makes me have to reconsider using C . Last year, when I was writing later Mark / Space Mail software, I have the opportunity to use some of the C class libraries developed by Brian Hall. Although these class libraries are not as rich as POL, but have not used all C technologies of professors in computer classes, but it does open my eyes, so I realize that these classes have been repeated in different applications. How simple is it.
Like other programming languages, it also has the same advantages and disadvantages using C . I have seen some business code, and their authors believe that all programs must be implemented with C . I think these developers are students who have just graduated from the university's computer system, want to use everything from school to learn from school in a Palm OS program. I think it is not a better way to use C on Palm OS. Palm OS programming is well used well, and some parts are not used. Instead, I see that some code uses very simple C features to organize functions and can easily access public variables of these functions. Of course, there must be developers disagree with this view. If the code becomes too complicated due to inheritance, virtual functions, etc., it is not suitable for C . I don't want to be a C expert, a lot of characteristics in C (for example, template) I have not used it. However, because of the large number of Palm OS and C programming, I know that even the most basic use of C can also be reused to speed up the development speed.
I found that using C in the Palm OS application is the following main advantages:
Code reuse. Most developers have written multiple Palm OS applications that there are many identical parts. There is no reason to rewrite the same code over and over again.
A bug is amended, all applications that use this class will be corrected. Conversely, if a class appears a bug, then all applications that use it will also appear at the same time. In some of my development, I use a class library based on TCP / IP protocol. As long as you fix errors in major classes, you will affect all applications that use it. For example, Mark / Space Mail and Mark / Space Online use a public TCP class, so that a bug fix will affect these two products. Data and function package. I always teach you, and should not use global variables in your application. However, this approach is not practical, so I will limit the use of global variables, so that it can improve the readability of the code and easier to maintain. Pack the approximation function into a class to improve the readability of the code.
There is also other advantages on the Palm OS and other platforms, but it is just the reason I personally like to use C . With the increase in memory on the Palm OS device, I did not find any of the disadvantages of using C .
People who write multiple database programs with C will know how boring the common functions of accessing the database over and over again. There is no doubt that you will definitely copy those major database code over and over again. At this time, use C or a relatively perfect solution. When I first saw the implementation of the database class, I think this is the best use of C . I have a few database classes here. In this article, I will give a simple database class to demonstrate how easy it is to use C in the application.
The code in this article can be used in any development environment. These codes are free, but have not been fully tested. When writing this article, I tested these code on Mac OS X using GCC.
let's start. Most of the example code in the Palm OS SDK has access one or more databases. Access to the database spreads throughout the program, and each program is used to access the database. For example, sample mail takes a record through the following code:
Err MailgetRecord (DMOPENREF DBP, UINT16 INDEX, MAILDBRECORDPTR R,
MemHandle * Handlep)
{
MemHandle Handle;
MailpackedDbrecordptr SRC;
Handle = DMQueryRecord (DBP, INDEX);
ErrfatalDisplayif (DMGetLasterR (), "Error Querying Record");
SRC = (MailpackedDbrecordptr) MemHandLock (Handle);
IF (DMGetLasterR ())
{
* Handlep = 0;
Return DMGetLasterR ();
}
MailunpackRecord (SRC, R);
* Handlep = Handle;
Return 0;
}
The code of the example Address is as follows:
Err AddrDBGetRecord (DMopenRef DBP, UINT16 INDEX, AddrDbRecordptr Recordp,
MemHandle * Recordh)
{
PrvadDrPackedDbrecord * SRC;
* RECORDH = DMQueryRecord (dbp, index);
SRC = (prvaddrpackedDbrecord *) MemHandLock (* Recordh);
IF (src == NULL)
Return DMerrindexOutofrange; PrvadDrDbunpack (SRC, RECORDP);
Return 0;
}
You have also seen it, the things you do in both functions are actually the same. However, they have a little difference in error checking. I suspect that one of them has been modified, and the other is not. If these two functions are encapsulated in class cDatabase, the modifications to one of them will also be applied to the other. Thus, you don't have to find the same bug between several items to make the same modification.
All database access programs I have written will be used in the following simple functions: Open, close, query records, create records, delete records, and sort. Many other functions are used when processed the database, just briefly introduce a function other than sorting and creating records. We use basic CDatabase classes and inherent CMAILDATABASE classes to demonstrate that the reuse is very easy. Remember, this is just an example, and may not be used directly in your program. In addition, other developers have different coding styles to organize classes in different ways. Here is just use examples to demonstrate how the C class simplifies the development process. As long as you write basic CDatabase classes, all applications can use it. Creating this class requires some time, but will save more time from this class.
The header file of the CDATABASE class is similar to the following code:
#ifndef __cdatabase_h__
#define __cdatabase_h__
#define norecordselected 0xffff
Class CDATABASE
{
PUBLIC:
CDATABASE (VOID);
~ CDATABASE (VOID);
Err Open (uint32 type, uint32 creator, uint16 mode, char * name);
Err RemoveRecord (Uint16 RecordIndex);
Err RemoveCurrentRecord (Void);
protected:
UINT32 mType;
Uint32 mcreator;
Err Create (Char * name);
Private:
DMOPENREF MDATABASEREF;
UINT16 MCURRENTRECORDINDEX;
Err QueryRecord (Uint16 RecordIndex, Void * Recordp, MemHandle * Recordhandle);
Err UnpackRecord (Void * SRC, VOID * DESTINATION);
}
#ENDIF
This type of constructor and the designer function are very intuitive.
// CDatabase Constructor
CDatabase :: cdatabase ()
{
McURRENTRECORDINDEX = NORECORDSELECTED;
MDATABASEREF = NULL;
MTYPE = 0;
McReator = 0;
}
// CDATABASE DESTRUCTOR
CDATABASE :: ~ cdatabase ()
{
IF (MDATABASEREF! = NULL)
{
(void) DMCloseDatabase (MDATABASEREF);
}
}
If the database is open, the destructor will turn off it. Turn off the database in the destructor and make sure to delete the used object, so that the database is always turned off.
I found that in most cases, when the database does not exist, you need to create one. Therefore, the OPEN method considers this, it will try to create one when the database does not exist.
// CDatabase :: Open (uint32 type, uint32 creator, uint16 mode, char * name)
{
Err err = errnone;
IF (Type == 0 || Creator == 0)
{
Return DMERRCANTFIND;
}
MTYPE = TYPE;
McReator = CREATOR;
MDATABASEREF = DMOPENDATABASEBYTYPECREATOR (Type, Creator, Mode);
IF (MDATABASEREF == NULL)
{
Err = DMGETLASTERR ();
// if we can't open the database because it doesn't exist, crete it
IF (Err == DMERRCANTFIND)
{
Err = CREATE (Name);
IF (Err == Errnone)
{
MDATABASEREF = DMOPENDATABASEBYTYPECREATOR (Type, Creator, Mode);
IF (MDATABASEREF == NULL)
{
Err = DMGETLASTERR ();
}
}
}
}
Return ERR;
}
// Create The Database Given a name
Err CDATABASE :: Create (char * name)
{
Err err = errnone;
IF (Name == Null)
{
Return DMERRCANTFIND;
}
Err = DMCreatedTabase (0, Name, McReator, mtype, false);
Return ERR;
}
These codes do not need to be explained for developers who are familiar with the Palm OS database. This code is mainly attempting to open the database with the specified type and creator (of course, this section does not process the situation where you need to access one or more of the same type and the creator's database, for example, read data from a set of e-books ). This code can be used well in the Address book and Mail programs.
All applications that use databases access records in the database. You will remember that Query calls are used when retrieving records in a read-only manner. In the Query routine of the CDATABASE class, "decompression" will be "unzipped" after querying the record. As shown in the example of Address book and mail applications, records in the database are saved in compression format, which saves space. Since each database compresses and uncompresses a record in different ways, I only created a universal decompression routine, which will be overwritten by the class in the Address book and Mail programs.
Err CDATABASE :: QueryRecord (uint16 recordindex, void * recordp, memhandle * recordhandle)
{
Void * SRC;
Err err = errnone;
McURRENTRECORDINDEX = NORECORDSELECTED;
IF (MDATABASEREF == NULL)
{
Return DMerrnoopendatabase;
}
* RecordHandle = DMQueryRecord (MDatabaseEref, RecordIndex);
IF (* recordhandle == null)
{
Return DMerrNotvalidRecord;
}
SRC = MEMHANDLOCK (* RecordHandle);
IF (src == NULL)
{
Return DMerrindexOutofrange;
}
Err = UnpackRecord (src, rordp);
IF (Err! = Errnone)
{
MemHandleunlock (* RecordHandle);
}
McURRENTRECORDEX = RecordIndex;
Return ERR;
}
Err CDATABASE :: UnpackRecord (Void * SRC, VOID * DEST)
{
Err err = errnone;
Return ERR;
}
The last method I provide in the base class is used to delete records. You must first create a record before you can delete it. The method of creating a record is left to the reader as an exercise.
Err CDATABASE :: RemoveRecord (uint16 inrecordindex)
{
Err err = errnone;
IF (MDATABASEREF == NULL)
{
Return DMerrnoopendatabase;
}
Err = DmremoveRecord (MDatabaseEref, INRECORDINDEX);
IF (INRECORDINDEX == McURRENTRECORDINDEX)
{
McURRENTRECORDINDEX = NORECORDSELECTED;
}
Return ERR;
}
Err CDATABASE :: RemoveCurrentRecord (Void)
{
Return RemoveRecord (McURRENTRECORDINDEX);
}
These functions are not complicated, demonstrating how to add a simple error handling mechanism in the base class, so that the entire program is not processed throughout the program. Your error handling in your code, is this? Since the RemoveRecord method has processed the case where the database reference is empty, you don't need to check when you call DmremoveRecord each time.
Now the base class is created, and the remaining parts of this article will give a simple derivative class, which can be used in the Mail application and some calls can be used in this new class.
To create a CMAILDATABASE class, simply override a method (in this case in the unpackrecord method).
#ifndef __cmailsDatabase_h__
#define __cmailsDatabase_h__
#include "cdatabase.h"
Class CmailDatabase: Public CDATABASE
{
Private:
Err UnpackRecord (Void * SRC, VOID * DESTINATION);
}
#ENDIF
The UnpackRecord function is as follows:
Err CmailDatabase :: UnpackRecord (Void * Insrc, Void * InDest)
{
Err err = errnone;
MailpackedDbrecordptr SRC = Insrc;
MAildbRecordptr dest = indest;
Char * p;
DEST-> DATE = SRC-> DATE;
DEST-> TIME = SRC-> TIME;
DEST-> FLAGS = SRC-> Flags;
P = & src-> firstfield; // Get the "subject" field.
IF (* P)
{
DEST-> SUBJECT = P;
P = Strlen (P) 1;
}
Else
{
DEST-> SUBJECT = P;
P ;
}
// ETC.
Return ERR;
}
As you can see, as long as you work, you can create a CMAILDatabase class that opens the database and access the record. In our primary code, all code to access the database is:
GmailDatabase = new cmails;
GmailDatabase-> Open (MAildbType, sysfilecmail, dmmodereadwrite, "maildatabase");
After using it, you can remove the object:
DELETE GMAILDATABASE;
Although this example is very simple, it does demonstrate the function of creating a universal C class for common functions. To make this class's functionality, it is also necessary to add a method for creating records, sorting, and the like. In addition, a method may also be added to convert the return value of the QueryRecord method to the correct type, so that you don't have to convert each time you call it.
There are some precautions when using C , this article has not been mentioned. They include:
Non-global code uses virtual functions (this is not done in most cases).
Abnormal handling will take up additional memory. If C exception is used, the compiler will generate additional code for this. If no exception is required, it is sure that this is closed in the compiler.
Limitations of abnormal processing. In some particular circumstances, the abnormal processing mechanism cannot work. For example, you cannot skip the OS call throw anomalies (in the event handler, you cannot skip the frMdispatChevent throw an exception and then return to the main event loop).
Although C has so many advantages in the development of Palm OS, unfortunately, most basic Palm OS programming books have not mentioned C . In addition, the sample code may check the C and simplify the code. As in this article, at least two (perhaps more) examples use repeated very similar routines (not exactly the same). As long as you are familiar with C how to use, there is no reason to use it in the program of Palm OS. For most of the code, C code multiplexing and convenient data packages can benefit you.
Thanks to Neil Rhodes, Steve Lemke and Brian Hall review and enroll in this article.
About author
Scott Gruby is an independent software developer who lives in San Diego. He is working in Palm OS development for more than 6 years. Developed from smart phone to the development of email applications and keyboard drivers, he made a lot of projects. If you need an expert with an experienced developer or an expert in an user, he is a very suitable partner. You can contact the author through PalmDeveloper@gruby.com.
note:
This article comes from the PalmSource Developer Website:
Http://www.palmsource.com/developers/, licenses that have been licensed using PalmSource.