Symbian中的Descriptor


Descriptorclasses can be classified according to where their data buffer is located:

stack descriptor     :  data buffer is as part of themselves

heap descriptor      :  data bufferis stored in the heap.

pointer descriptor  :  does not own data buffer,

                                       databuffer they pointed to can be anywhere.

 

 

TLitC and TPtrCare not modifiable at all, however TBufC and HBufC are not directly modifiable,but they are indirectly modifiable.

 

1.  Literals

Literals areusually referred to as literal descriptors; because they are stored in the programbinary, they are also sometimes referred to as program binary descriptors. As programbinary is executed either directly from ROM or from read-only RAM, literals arealso read-only.

In standard C++,literal can be included in the program binary by declaring them as staticconstant:

static const charKTxtHelloWorld[] = "Hello World!";

In Symbian OS,literal is included in the program binary by using TLitC class, however younever actually use this class directly, instead you use it indirectly via themacro _LIT as follows:

_LIT(KTxtHelloWorld,"Hello World!");

The binary layoutof TLitC is designed to be identical to a TBufC, which allows TLitC to betreated as descriptor. Although literals aren’t actually descriptors, they canbe converted to descriptor by usingoperator()()method.

 

2.  Stack Descriptors

 

3.   Pointer Descriptors

All TPtrs aretype 2 unless they are created by using HBufC::Des() or TBufC::Des() methods.

Be aware that ifyou have more than one type 4 TPtr pointing to the same HBufC or TBufC, thenmodifications made via one are not reflected in the others.

4.   Heap Descriptors

Heap descriptors havetheir data buffer created in the heap. With both RBuf and HBufC, if the heap buffersize needs to be expanded, it can not be done automatically, you must resize thedescriptor manually by using ReAlloc() or ReAllocL().

4.1  HBufC

The stackdescriptors, TBuf and TBufC, are templated, and the template value determinesthe length of the data area.

HBufC is slightlydifferent. To save memory, HBufC does not store its maximum length; instead, itfinds out its maximum length by finding out the size of the heap cell where itis stored.

Heap cells havedifferent granularity that depends on the specific hardware to which Symbian OShas been ported. When allocating memory, Symbian OS always rounds up to thenext nearest granularity boundary, so if you create HBufC with a specificlength, you may end up with a bigger descriptor than you asked for.

4.2  RBuf

All RBufs aretype 2 unless they take ownership of an existing HBufC by using constructorRBuf(HBufC *aHBuf) or Assign(HBufC16 *aHBuf).

Create() and Assign()orphans any data already owned by the RBuf, so Close() should be called whereappropriate to avoid memory leaks.

5.  Descriptors as Parameters

• To pass a descriptor as an input parameter into a method (i.e., to pass descriptor datathat is read within the method but is not changed), use const TDesC&as the parameter type.

• To pass an in–out parameter to a method (i.e., to pass descriptor data that youwant to change within your method), use TDes& as the parameter type.

If you need tocreate a heap buffer within your method and pass ownership to the callingcode, then the choice is between an HBufC and an RBuf.

The standardpattern for creating an HBufC is to return it from the method.

HBufC*CSomeClass::GetSomeTextL()

    {

    HBufC* hBuf =iEikonEnv->AllocReadResourceL(someResourceID);

    return hBuf;

    }

HBufC* hBuf = GetSomeTextL();

. . .

delete hBuf;


Usually, if amethod needs to create an HBufC and pass ownership of it to thecaller this is done by returning it, however there may be circumstanceswhen something else must be returned from the method.

In thesecircumstances, this can be accomplished using a parameter instead:

TIntFooL(HBufC*& aBuf)

    {

    ASSERT(aBuf ==NULL);

    aBuf =KTxtHelloWorld().AllocL();

    return KErrNone;

    }

HBufC* buf =NULL;

FooL(buf);

delete buf;


Note that if theHBufC needs to be created before being passed to a method andassigned within the method, then this can also be accomplishedusing an HBufC*& parameter, though if you need to use ReAlloc() withinthe method, then caution should be exercised (see Section 5.11).

If the heapdescriptor is not written to or is written to infrequently then use HBufC;however if the heap descriptor is to be written to frequently then an RBuf ispreferable as it is more efficient.

An RBuf cannot bereturned from a method as its copy constructor is protected,

voidcopyTextL(RBuf& aDes)

    {

    _LIT(KTxtHello,"Hello");

    if(aDes.MaxLength() < KTxtHello().Length())

        {

        aDes.ReAllocL(KTxtHello().Length());

        }

    aDes = KTxtHello;

    }

6.  Correct Use of Descriptors

Do Not Declare TDesC or TDes Variables

TDesC and TDes donot contain any actual data, thus you should never instantiate TDesC or TDes.

_LIT(KTxtHelloWorld,"Hello World!");

// compile successfully,but neither hold the actual data

TDesdes(KTxtHelloWorld);

TDesCdesC(KTxtHelloWorld);

Always Pass TDes and TDesC Parameters by Reference

The reason isthat TDesC and TDes do not contain any actual data. If you pass them by value, thepolymorphism won’t work. The end result is that your code compiles but you are notactually passing any data.

Always Define const when Declaring TDesC Parameters

If omit the const keyword when declaring TDesC parameter, a compilation error maybe generated depending upon the compiler used. Even if no compilation errorgenerated for the function declaration, when calling this function and passinga literal to that parameter does lead to a compilation error.

Do Not Place Large Stack Descriptors on the Stack

A Symbian OS ruleof thumb is that if something is more than 256 bytes, then it shouldn’t go onthe stack (the stack size is pretty limited: the default is 8 KB). So, youshould consider using RBuf or HBufC instead.

It is advisableto be aware of the following types:

TEntry consumes 552 bytes

TFileName consumes 520 bytes

TFullName consumes 520 bytes

TName consumes 264 bytes.

Be Wary of HBufC::ReAllocL() and HBufC::ReAlloc()

The call toReAllocL() creates a new heap descriptor and, if successful, copies theoriginal data into it and returns the new address. The original copy is deleted.After reallocation, the new heap descriptor may be located in a different heapcell.

This is particularlyimportant if you use Des() method, in which case you need to re-Set() any TPtrreturned by Des().

Besides, you mustpay attention if you are pushing HBufC s to the cleanup, in which case you needto pop the original HBufC address off the stack, and re-push the new one.

Use _LIT Instead of _L

_LIT macro ismore efficient than _L. Although _L is deprecated, it is still acceptable to usebecause it doesn’t have to be declared separately:

User::Panic(_L("ServerPanic"), KPanicCode);

############# _Land _LIT are defined in e32def.h ##################

#ifdefined(_UNICODE)

#define _L(a)(TPtrC((const TText *)L ## a))

#define_LIT(name,s) static const TLitC<sizeof(L##s)/2>

name={sizeof(L##s)/2-1,L##s}

#else

#define _L(a)(TPtrC((const TText *)(a)))

#define_LIT(name,s) static const TLitC<sizeof(s)>

name={sizeof(s)-1,s}

#endif

Avoid Declaring Literals in Header Files

When usingliterals, try not to declare them in the header file because all CPP filesincluding it will generate a new copy, which can lead to code bloat.

Instead put _LITsin the CPP file.

Initialize TPtr Class Data Members

TPtr does nothave a default constructor, so when it is used as a data member of a class, itmust be initialized in the constructor’s initialization list, otherwise acompilation error will be generated.

 

#include <e32base.h>
#include <e32cons.h>
void HelloWorldL(void)
        {
        // Create a literal descriptor
        _LIT(KTxtHelloWorld, "Hello World!");
        const TInt KHelloWorldLength = 12;
        
        // create aTBuf
        TBuf<KHelloWorldLength> tbuf(KTxtHelloWorld);
        
        // create a TBufC
        TBufC<KHelloWorldLength> tbufc(KTxtHelloWorld);
        
        // create an HBufC
        HBufC* hbufc = KTxtHelloWorld().AllocLC();
        
        // Create an RBuf
        RBuf rbuf;
        rbuf.CreateL(KHelloWorldLength, KTxtHelloWorld);
        rbuf.CleanupClosePushL();
        
        // create a TPtrC
        TPtrC tptrc(tbufc);
        
        // create a TPtr
        TPtr tptr = hbufc->Des();
        
        // display "Hello World!" 7 times to the text console
        CConsoleBase* console = Console::NewL(KTxtHelloWorld, TSize(KConsFullScreen,KConsFullScreen));
        console->Printf(KTxtHelloWorld);
        console->Printf(tbuf);
        console->Printf(tbufc);
        console->Printf(tptr);
        console->Printf(tptrc);
        console->Printf(*hbufc);
        console->Printf(rbuf);
        console->Getch(); // pause until user enters input
        CleanupStack::PopAndDestroy(2);
        delete console;
        }
        
GLDEF_C TInt E32Main()
    {
    static CTrapCleanup* cleanup = CTrapCleanup::New();
    TRAPD(ret,HelloWorldL());
    delete cleanup;
    return (0);
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值