Helloworld程序详解
[size=16px][/size]Hello World!First step to Symbian
S60 SDK的HelloWorldBasic例子@C:\Symbian\9.2\S60_3rd_FP1\S60Ex\HelloWorldBasic\group\bld.inf
详细文档@C:\Symbian\9.2\S60_3rd_FP1\S60Ex\HelloWorldBasic\doc
导入C:\Symbian\9.2\S60_3rd_FP1\S60Ex\HelloWorldBasic\group\bld.inf进Carbide C++
详细来看下Symbian的应用程序启动
1. EXE文件自E32Main()入口(在helloworldbasic.cpp中)
E32Main()调用NewApplication()创建一个HelloWorldApplication类实例,并返回其指针。Symbian随后使用该指针完成application的创建。
/**
* A normal Symbian OS executable provides an E32Main() function which is
* called by the operating system to start the program.
*/
GLDEF_C TInt E32Main()
{
return EikStart::RunApplication( NewApplication );
}
在同文件(helloworldbasic.cpp)中可以看到CHelloWorldApplication的创建
/**
* factory function to create the Hello World Basic application class
*/
LOCAL_C CApaApplication* NewApplication()
{
return new CHelloWorldBasicApplication;
}
下面跟踪一下Symbian的具体系统实现:
在eikstart.h里面来仔细看一下EikStart::RunApplication()
class EikStart
/**
This is the API to initialise and run the application architecture for applications built as exes.
It is not intended to be used for generally running applications from other code. Use RApaLsSession for that.
@publishedAll
@released
*/
{
public:
IMPORT_C static TInt RunApplication(TApaApplicationFactory aApplicationFactory);
private:
static void RunApplication(const TApaApplicationFactory& aApplicationFactory,CApaCommandLine* aCommandLine);
};
#endif
定义里面有一个工厂类TApaApplicationFactory,该类可以看作是建立应用程序的工厂。
在E32Main()函数中EikStart::RunApplication( NewApplication ),参数却是指向NewApplication函数的指针。
到apparc.h中去看TApaApplicationFactory类的定义:
class TApaApplicationFactory
/** Encapsulates the functionality of creating an application, whether it be via a factory function
or an ECOM plugin. Instances of this class can usually be created implicitly when required as
function parameters - just specify the function pointer, ECOM plugin UID or CImplementationInformation
reference.
@publishedAll
@released
@see CApaProcess
@see EikStart */
{
public:
typedef CApaApplication* (*TFunction)();
public:
IMPORT_C TApaApplicationFactory();
IMPORT_C TApaApplicationFactory(TFunction aFunction);
IMPORT_C TApaApplicationFactory(const CImplementationInformation& aEmbeddedApplicationInformation);
IMPORT_C TApaApplicationFactory(TUid aEmbeddedApplicationUid);
CApaApplication* CreateApplicationL() const;
HBufC* AppFileNameL() const;
TUid AppFileUid() const;
private:
enum TType
{
ETypeFunction, // if iType is this, iData is a TFunction
ETypeEmbeddedApplicationInformation, // if iType is this, iData is an ECOM CImplementationInformation
ETypeEmbeddedApplicationUid // if iType is this, iData is an ECOM implementation TUid
};
private:
static CApaApplication* CreateEmbeddedApplicationL(TUid aUid);
static HBufC* EmbeddedApplicationDisplayNameLC(TUid aUid);
static HBufC* FullAppFileNameL(const TDesC& aAppName);
static void CleanupImplementationArray(TAny* aImplementationArray);
private:
TType iType;
TUint iData;
mutable CApaApplication* iApplication; // used to be iSpare1
TInt iSpare2;
};
调用EikStart::RunApplication过程中,编译器创建一个TApaApplicationFactory对象,其构造函数的参数是NewApplication的函数指针。
这里面有隐式转换,可以查一下C++primer
we saw that a nonexplicit constructor that can be called with one argument defines an implicit conversion.the complier will use that conversion when an object of the argument type is suupplied and an object of the class type is needed .
可以以一个实参调用的非explicit构造函数(可能有默认参数)定义了一种隐式转换。
当我们需要该类类型对象时,而如果我们只提供了该类构造函数的形参类型的实参,这种转换就发生。
摘自C++primer 原版第四版 p535最后一段
conversion function can be defined for any type (other than void)that could be a function return type.in particular,convesions to an array or function type are not permitted.conversions to pointer types--both data and function poiters--and to reference types are allowed.
a conversion function must be a member function .the function may not specify a return type,and the parameter list must be empty.
摘自C++primer 原版第四版 p538第一段
这里还需要提到的是,CHelloNewApplication并没有使用Symbian最常见的new(ELeave)方式,而是使用了C++的new方式。这是因为在程序刚开始运行,TRAP harness还没有构建成功。如果系统不能为这个应用程序实例分配内存,则返回的实例指针为NULL,系统是可以处理这种异常的。
2. 系统获取UID
系统获取UID比较简单,在CHelloWorldApplication::AppDllUid()返回。
本示例UID宏定义如下,0xA0000000 到 0xAFFFFFFF属于非保护UID,一般供测试使用。
const TUid KUidHelloWorldBasicApp = { 0xA000017F };
3. 建立Document实例
系统调用CHelloWorldApplication::CreateDocumentL()创建Document实例并返回其指针。
注意,此时创建实例已经使用了Symbian中推荐的NewL静态函数来创建实例
CApaDocument* CHelloWorldBasicApplication::CreateDocumentL()
{
// Create an HelloWorldBasic document, and return a pointer to it
return (static_cast<CApaDocument*> ( CHelloWorldBasicDocument::NewL( *this ) ) );
}
具体来看一下其NewL函数实现内容:
在NewLC()中分配指针,PushL到清栈中,然后调用构造函数进行创建
在NewL()中,对上述操作后追加Pop弹栈处理
为什么要有两个NewL和NewLC?
NewL和NewLC都返回指针,区别就在于使用NewL已经弹栈,而使用NewLC还在清栈。
如果后续立即就使用该指针,在Symbian OS中必须要在清栈中处理这些指针防止内存泄露。如果使用NewL创建,还需要重新PushL进清栈,使用完毕再PopL。对于这类使用,请使用NewLC。
// -----------------------------------------
// CHelloWorldBasicDocument::NewL()
// Two-phased constructor.
// -----------------------------------------
//
CHelloWorldBasicDocument* CHelloWorldBasicDocument::NewL( CEikApplication& aApp )
{
CHelloWorldBasicDocument* self = NewLC( aApp );
CleanupStack::Pop( self );
return self;
}
// -----------------------------------------
// CHelloWorldBasicDocument::NewLC()
// Two-phased constructor.
// -----------------------------------------
//
CHelloWorldBasicDocument* CHelloWorldBasicDocument::NewLC( CEikApplication& aApp )
{
CHelloWorldBasicDocument* self = new ( ELeave ) CHelloWorldBasicDocument( aApp );
CleanupStack::PushL( self );
self->ConstructL();
return self;
}
5. 创建AppUI实例
系统调用Document类中的CreateAppUiL函数CHelloWorldBasicDocument::CreateAppUiL()创建AppUI实例并返回其指针。系统调用CHelloWorldBasicAppUi::ConstructL() 构造函数完成AppUI实例创建。
AppUI实例构造暂不介绍,有兴趣可以查阅CHelloWorldBasicAppUi::ConstructL()
再次注意的是,创建AppUI并没有使用两阶段构造。因为AppUi所属于系统,Document类实例并不需要也没有权限去销毁。
CApaDocument* CHelloWorldBasicApplication::CreateDocumentL()
{
// Create an HelloWorldBasic document, and return a pointer to it
return (static_cast<CApaDocument*>
( CHelloWorldBasicDocument::NewL( *this ) ) );
}
6. 创建AppView实例
使用两阶段构造法,调用 CHelloWorldBasicAppView::NewL() 创建AppView实例。
7. Draw the AppView
调用CHelloWorldBasicAppView::Draw() 。需要注意的是此Draw() 只能响应系统,在编程过程中不能直接调用,而需要使用DrawNow()。
8. 响应Menu菜单
在CHelloWorldBasicAppUi::HandleCommandL() 中响应Menu菜单各指令。
详细不做介绍,最后提一下,case default中panic为Symbian的系统严重异常处理。
void CHelloWorldBasicAppUi::HandleCommandL( TInt aCommand )
{
// clear possible old user-given text
iAppView->GetText().Zero();
switch( aCommand )
{
case EEikCmdExit:
case EAknSoftkeyExit:
Exit();
break;
case EHelloWorldBasicCommand1:
{
// Load a string from the resource file and display it
HBufC* textResource = StringLoader::LoadLC( R_HEWB_COMMAND1_TEXT );
CAknInformationNote* note = new ( ELeave ) CAknInformationNote;
// Show the information Note with
// textResource loaded with StringLoader.
note->ExecuteLD( *textResource );
// Pop HBuf from CleanUpStack and Destroy it.
CleanupStack::PopAndDestroy( textResource );
}
break;
case EHelloWorldBasicCommand2:
{
RFs fsSession;
RFile rFile;
// Connects a client process to the fileserver
User::LeaveIfError(fsSession.Connect());
CleanupClosePushL(fsSession);
//Open file where the stream text is
User::LeaveIfError(rFile.Open(fsSession,KHelloFileName, EFileStreamText));
CleanupClosePushL(rFile);
// copy stream from file to RFileStream object
RFileReadStream inputFileStream(rFile);
CleanupClosePushL(inputFileStream);
// HBufC descriptor is created from the RFileStream object.
HBufC* fileData = HBufC::NewLC(inputFileStream, 32);
CAknInformationNote* note = new ( ELeave ) CAknInformationNote;
// Show the information Note
note->ExecuteLD( *fileData );
// Pop loaded resources from the cleanup stack:
// filedata, inputFileStream, rFile, fsSession
CleanupStack::PopAndDestroy(4, &fsSession);
}
break;
case EHelloWorldBasicCommand3:
{
// Load a string from the resources and use it as a default value
HBufC* defaultText = StringLoader::LoadLC( R_HEWB_FILE_TEXT );
CHelloWorldQueryDialog *dlg = new (ELeave)
CHelloWorldQueryDialog( iAppView->GetText(), defaultText );
dlg->ExecuteLD( R_DIALOG_TEXT_EDIT_QUERY );
// Pop HBuf from CleanUpStack and Destroy it.
CleanupStack::PopAndDestroy( defaultText );
}
break;
default:
Panic( EHelloWorldBasicUi );
break;
}
}
[解决办法]
支持分享~~
[解决办法]
学习了,谢谢!
[解决办法]
好,学习了,收下
[解决办法]
不错的程序
[解决办法]
xue xi xia
[解决办法]
好,学习了,收下
[解决办法]
难度很大的哦
[解决办法]
楼主好犀利啊
[解决办法]
好,学习了,收下
------解决方案--------------------
[解决办法]
受教了
[解决办法]
恩 非常好
[解决办法]
很有难度
[解决办法]
学习了,谢楼主
[解决办法]
[解决办法]
GOOD, THANKS FOR SHARING
[解决办法]
看起来很难得样子
[解决办法]
[解决办法]
支持分享。
[解决办法]
不 错
[解决办法]
[解决办法]
支持分享~~
[解决办法]
楼主细心,.........
[解决办法]
收藏学习
[解决办法]
MARK~~~
[解决办法]
学习,学习
[解决办法]
10.........................
[解决办法]
再次路过学习一下
[解决办法]
好长啊
[解决办法]
我现在知道为什么塞班系统作为一款手机平台有多失败了,开发个helloworld都如此繁琐,将多少手机应用开发者拒之门外啊。
没有丰富的手机应用作为支持,那手机就难以作为娱乐平台使用,不符合当前手机发展的趋势啊。
[解决办法]
不过相应的,塞班系统的稳定性是比较可取的,算是有得有失吧
[解决办法]
???
[解决办法]
jfzr
[解决办法]
太长@
[解决办法]
好好好好
[解决办法]
[解决办法]
每天回帖即可获得10分可用分
[解决办法]
代码不错呵
[解决办法]
不错,挺好的
[解决办法]
learning......