Assuming that the user is new to the UNIX environment, writing a simple program that displays a string on a console does not take more than a day’s effort. Its simply 4-5 lines of code as shown below:
#include <stdio.h> int main(int argc, char** argv) { printf(“Hello world\n”); return 0; }
The code contains a main() , one printf statement, and one #include< >. By convention UNIX applications will map descriptor 0 with standard input (STDIN), descriptor 1 with standard output (STDOUT), and descriptor 2 with standard error (STDERROR) of the process. So, there is no need to create/open standard input/output/error for a process before using them. Notice also that, main() takes two arguments. These arguments will be read from the command prompt before invoking main() and will be passed to main. These arguments are not mandatory; they can be ignored. No additional work is needed for having these arguments.
If the user attempts to display a string on a console using Symbian platform, a lot of effort goes into collecting the materials, and for coding. The first time the developer may find the code a little complex to understand.
#include <e32std.h> #include <e32cons.h> int HelloWorldL() { CConsoleBase* console = Console::NewL(_L("Hello World"), TSize( KConsFullScreen, KConsFullScreen)); console->Printf(_L(“Hello World\n”)); delete console; return 0; } TInt E32Main() { __UHEAP_MARK; CTrapCleanup* cleanup = CTrapCleanup::New(); TInt retVal = KErrNone; if (cleanup) { TRAP(retVal, HelloWorldL()); __ASSERT_ALWAYS(!retVal, User::Panic(_L("Hello-World PANIC"), retVal)); //Destroy cleanup stack delete cleanup; } __UHEAP_MARKEND; return retVal; }
The code above has some header inclusions, two functions, and some complicated codes. In Symbian platform, the entry function for an EXE is E32Main (not main as in UNIX). The following actions are done to print a message on a console:
Mark the heap using __UHEAP_MARK (not mandatory).
Create the cleanup stack. Have a top-level TRAP for the function HelloWorldL() function.
In the HelloWorldL() function, create a console object.
Do print on the created console object.
Delete the console.
Delete the cleanup stack.
Unmark the heap (not mandatory if the heap is not marked).
In Symbian platform, a console is not created by default; it has to be created explicitly. Symbian platform does not give a rich set of APIs needed to perform I/O operations on a console. The I/O operations that can be performed on a console in Symbian platform are limited to:
printing strings and reading one character at a time
getting cursor position
In case the user is interested in command line arguments, it takes some more additional work. The user must read explicitly from the command prompt by using the APIs provided by Symbian platform.
This section compares the ease of programming in the P.I.P.S. environment against programming on Symbian platform.
/* File I/O in UNIX environment */ FILE* fp = fopen(“file.txt”, w); if (fp) { fprintf(fp, “Write some data”); fclose(); }
//File I/O in Symbian platform RFs fSession; User::LeaveIfError(fSession.Connect()); RFile file; ret = file.Open(fSession, _L(“file.txt”), EFileWrite); if (ret) { ret = file.Create(fSession, _L(“file.txt”), EFileWrite); } if (!ret) { file.Write(_L8(“Write some data”)); } file.Close(); fSession.Close();
The example above shows the complexity of the code in Symbian platform for doing simple file I/O. In addition to coding complexity, the user must include and link with:
efsrv.lib for any file-related operation
esock.lib for network-related operation
commdb.lib for selecting IAPs
connect with the file server before file operations
connect with the socket server for socket-related operation
connect to the communication server before serial communication operation
P.I.P.S. eliminates all these operations. P.I.P.S. allows the user to code, as if it were done for the UNIX or Linux environment and lets the user link the application with P.I.P.S.
This section deals with thread creation in the UNIX and Symbian platform environments.
/* Thread creation in UNIX environment*/ void* ThreadEntryPoint( void* aParam ); int exitReason = 0; int retVal = 0; pthread_t threadID = 0; pthread_attr_t threadAttr; pthread_attr_init(&threadAttr); retVal = pthread_create(&threadID, &threadAttr, ThreadEntryPoint, (void*)NULL ); if(retVal == 0) { retVal = pthread_join(threadID1, (void**)&exitReason); }
// Thread creation in Symbian Platform TInt ThreadEntryPoint( TAny* aData ); … RThread thread; thread.Create(_L("MY-THREAD"), ThreadEntryPoint, 4096, NULL, NULL); TRequestStatus stat; thread.Logon(stat); //Start executing the thread. thread.Resume(); //Wait for the thread to die. User::WaitForRequest(stat); exitReason = thread.ExitReason(); thread.Close();
In addition the difference in the code for creating threads using pthread_create and RThread::Create(), a thread created using RThread::Create() also expects the ThreadEntryPoint() function to create its own vcleanup stack and a top-level TRAP, if required. Else, the thread may crash or panic. But this does not have to be done for a thread created using pthread_create. pthread_create does that for the developer.