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.