Wiley.Developing.Software.for.Symbian.OS.2nd.Edition.Dec.2007 (779887), страница 25
Текст из файла (страница 25)
TARGETTYPE dll determines that thebinary type is that of a shared library.TARGETmydll.dllTARGETTYPEdllUID0x1000008d 0xE0004264SOURCEPATH..\srcSOURCEmydll.cppUSERINCLUDE.USERINCLUDE..\includeSYSTEMINCLUDE \Epoc32\includeEXPORTUNFROZENLIBRARIES1174.6.2 Import LibrariesWhen you build a DLL, you actually build two files: a DLL and a staticlibrary (which can be a LIB or DSO file depending on your build target, seesection 5.4.2). The static library is known as an import library. Programsthat use a DLL will statically link to its import library. Import librariescontain function wrappers for each DLL function that, when run, willlocate and execute the real function’s code in the appropriate runtimeloaded DLL. The import library also handles the details of loading theappropriate DLL, if it is not already loaded.For your program to use a DLL, you link at build time to the DLL importlibrary by adding it to your LIBRARY line in your MMP.
Then, as long asthe DLL exists on your target, your program can invoke the exported DLLclasses and functions as needed.The system APIs are implemented as DLLs. The SDK will indicatewhat include file to use as well as what import library to include in theLIBRARY line of your project’s MMP file.4.6.3RLibrary APIAs an alternative to static linkage to a library, you can use the RLibraryAPI to dynamically load it into memory and invoke its exported functions.The functions are invoked by ordinal number, and you have to knowwhat functions correspond to what ordinal. Exporting library functionsby ordinal numbers and RLibrary are described in more detail inChapter 5.4.6.4 Polymorphic DLLsA polymorphic DLL is a normal shared library, but with only one exportedfunction – a factory function that creates an instance of an object andreturns it, as shown below.//H fileIMPORT_C MPolyInterface *NewMyPolyL();class CMyDerivedPolyPlugin : public CBase, public MPolyInterface{// ...};// CPP fileEXPORT_C MPolyInterface *NewMyPolyL(){return new(Eleave) CMyDerivedPolyPlugin;}// Implement rest of class member functions hereAs covered in Chapter 3, polymorphic DLLs implement virtual functions, typically those defined in M class interfaces.
You can create multiple118SYMBIAN OS PROGRAMMING BASICSpolymorphic DLLs that all implement this NewMyPoly() function, butreturn different MPolyInterface-derived class implementations. Theprogram then chooses which of these DLLs to load, and loads it with theRLibrary load command. Then, the program executes common codethat uses the DLL class through the common base pointer (i.e., MPolyInterface). This common code does not care which plug-in DLL hasbeen loaded.4.6.5 Static Data in DLLsSymbian OS versions before v9 do not allow you to have writablestatic data in a DLL, although Symbian OS v9 and above do allowit.
As I mentioned in Chapter 3, even in Symbian OS v9, writablestatic data is strongly discouraged in library code. This is a designpreference for efficient use of memory. Tacking on a data memoryregion for DLLs is costly considering the large number of DLLs available.It can be a challenge sometimes to not use any static data in DLLs,especially true when porting existing code. Note that you can have globalvariables – they just should be read-only (i.e., of type const).For Symbian OS versions before v9, be aware that the emulator willallow you to put static data in your DLLs, however, the target systemwill not.
This can surprise you if you have been doing the bulk of yourdevelopment on the emulator and then do your initial build using thesmartphone target ARM tools and get errors that look something like thisone:PETRAN - PE file preprocessor V01.00 (Build 175)Copyright (c) 1996-2000 Symbian Ltd.ERROR: Dll ‘XXXApp[appUid].APP’ has uninitialized data.NMAKE :fatal error U1077: ‘petran’ : return code ‘0xfffffffe’Stop.4.7 Executable FilesThe EXE file is the basic executable image file for Symbian OS and allprocesses reside in one.
For example, in Symbian OS v9 and above,GUI applications are EXE files. In Symbian OS releases before v9, a GUIapplication was actually a DLL, and was launched transparently from anEXE file called apprun.exe.You may need to implement your own EXE files for non-GUI processesas well, such as if you implement a server. The following example showsa simple EXE:NAMING CONVENTIONS119TInt ExtGlobal=0;// ok to use here in EXEGLDEF_C TInt E32Main(){for (;;){User::After(10000000); // wait 10 secondsUser::InfoPrint(_L("Ping Message"));ExtGlobal++; // Used to illustrate that you can use// writable globals in exe files}}This is the corresponding MMP file for building the source of this EXE:// exe mmp fileTARGETmyexe.exeTARGETTYPEexeSOURCEPATH..\srcSOURCEmyexe.cppUSERINCLUDE.USERINCLUDE..\includeSYSTEMINCLUDE \Epoc32\includeLIBRARYeuser.libThe executable in the example above loops for ever and displays amessage to the screen every 10 seconds.
InfoPrint() function displaysa message for a short period of time before it disappears (until invokedagain after the next User::After()).As you can see, the basic structure of an EXE is simple. The EXE onlyrequires the entry point E32Main() and your code takes it from there.TARGETTYPE exe indicates that the output is an EXE file.Note that you can use writable static data in EXE files even in preSymbian OS v9 versions.An application can start an EXE file by using the RProcess class,which is discussed in Chapter 9.4.8 Naming ConventionsSymbian OS has a set of naming conventions that should be used whendeveloping Symbian OS software.
The operating system itself uses thesefor its APIs and data.Naming conventions make code easier to understand and aid correctusage of classes and variables. For example, code such as the following(which appears to be pushing member data to the cleanup stack, sincethe ‘i’ prefix indicates a member variable) should be regarded withsuspicion:120SYMBIAN OS PROGRAMMING BASICSCleanupStack::PushL(iMyData)This is because you should never push a class member variable on thecleanup stack.Another suspicious line would be:CSomeClass sc;A class based on CBase (indicated by the prefix C) should neverbe statically instantiated or instantiated on the stack – new (or a staticNewL()/NewLC()) should be used instead.Yet another example is if you see a class that begins with an R(a resource class) and no Close() function called on it – that shouldencourage you to look at it more closely.Class namesWe looked at the conventions for class names at the beginning of thischapter.
To recap: T is prefixed to structures and class names thatrepresent data types, C is prefixed to the names of heap classes derivedfrom CBase, R is prefixed to resource class names, and M is prefixed tointerface class names.Variable namesClass member variables should begin with ‘i’. Function arguments shouldbegin with ‘a’. For example:class TMyClass{public:...TInt iMyValue;void MyAddFunc(TInt aArg1, TInt aArg2);};void TMyClass::MyAddFunc(TInt aArg1, TInt aArg2){iMyValue = aArg1+aArg2;}Global variables (although their use is discouraged) should begin withan uppercase character.ConstantsPrefix constants with K. For example:const TInt KMyConstant=3;NAMING CONVENTIONS121or_LIT(KMyConstantString,"string");)EnumerationsEnumeration types begin with T (since they are types). The actual enummembers should begin with E.
For example:enum TColors{ERed,EGreen,EBlue,EPurple,...};MacrosMacros should be all uppercase. For example:#define MY_HARDCODED_VALUE 25Function namesFunction names should be descriptive and, in most cases, are verbs.Function names have suffixes to indicate if they could leave on anerror, and/or if they push anything on the cleanup stack. We’ve lookedat these suffixes already when discussing error handling, but here is arecap:•L – Functions in which a leave may occur end in L (e.g., myFuncL()).•LC – Functions that may leave, having previously pushed their resultsto the cleanup stack, end in LC.A function suffix not previously discussed is D. A class method endingin D means that the function takes responsibility for the object themethod is called from – that is, it will delete the object when it isfinished with it.
Thus, the calling program should not delete it (yoursoftware will crash if you do!). An example function of this type is thedialog function CEikDialog::ExecuteLD(), which will launch thedialog and destroy the dialog object itself once the dialog is dismissedby the user (note the L before the D, which indicates it may alsoleave).122SYMBIAN OS PROGRAMMING BASICS4.9 SummaryThis section recaps some key points to remember when developingSymbian OS software. Some of these have already been discussed andare included here again for convenience.•When calling functions that may leave, consider what happens if theprogram exits at that point and use the cleanup stack as needed toprevent memory leaks.•Any function that has a possibility of leaving should end in L (e.g.,FooL()).•Consider using the overload of operator new for instantiating objectswithout having to check that the pointer returned is valid (e.g., CClass= new(ELeave) CClass).