symbian官方推薦使用活動(dòng)服務(wù)對(duì)象(CActive)來(lái)代替多線程的使用,我想這個(gè)道理是很明了的,在手機(jī)這樣的小內(nèi)存設(shè)備里,運(yùn)行多線程的程序是非常耗資源的,為了節(jié)約資源,symbian提供了一個(gè)活動(dòng)服務(wù)對(duì)象的框架,允許把程序里并發(fā)執(zhí)行對(duì)象(其實(shí)不是并發(fā),不過(guò)宏觀上看來(lái)是)放在一個(gè)線程里面執(zhí)行,這些并發(fā)工作的對(duì)象就通過(guò)活動(dòng)規(guī)劃器(ActiveScheduler)來(lái)進(jìn)行管理.
關(guān)于這兩個(gè)東西的介紹,網(wǎng)上有一大堆的文檔,我就不在這里廢話了,如何使用呢?這里我先舉一個(gè)簡(jiǎn)單的計(jì)數(shù)器的例子.我選擇寫(xiě)一個(gè)exe的程序,也就是說(shuō)程序是以E32Main為入口的.
GLDEF_C TInt E32Main()
{
CTrapCleanup* cleanup=CTrapCleanup::New();
TRAPD(error,callInstanceL());
if (error != KErrNone)
{
printf("get error %d\r\n", error);
}
delete cleanup;
return 0;
}
以上的內(nèi)容是每一個(gè)exe文件都應(yīng)該做的,CTrapCleanup* cleanup=CTrapCleanup::New()建立一個(gè)清除堆棧,以便程序在異常退出的時(shí)候把清除堆棧里面的資源都釋放掉.當(dāng)然你也可以加上堆檢測(cè)宏(__UHEAP_MARK,__UHEAP_MARKEND),這里我就不多說(shuō)了。TRAPD是symbian里面經(jīng)常使用的宏,功能類似于try,第一個(gè)參數(shù)是讓定義一個(gè)錯(cuò)誤返回值變量的名字, 后面就是可能有異常的你寫(xiě)的函數(shù).當(dāng)這個(gè)函數(shù)異常時(shí),程序不會(huì)crash, 你可以得到異常的原因.可以參考nokia論壇上的一些關(guān)于這些使用的文檔.
接下來(lái)是vcallInstanceL函數(shù),在這個(gè)函數(shù)里面我來(lái)建立ActiveScheduler.
LOCAL_C void callInstanceL()
{
CActiveScheduler* scheduler = new(ELeave) CActiveScheduler();
CleanupStack::PushL(scheduler);
CActiveScheduler::Install(scheduler);
TRAPD(error,doInstanceL());
if(error)
{
printf("error code=%d\r\n",error);
}
else
{
printf("OK!\r\n[press any key]");
}
CleanupStack::PopAndDestroy(scheduler);
}
這段程序很簡(jiǎn)單就是創(chuàng)建一個(gè)活動(dòng)規(guī)劃器,并壓入清除棧,然后安裝活動(dòng)規(guī)劃器,這樣就可以用了.再執(zhí)行真正的實(shí)例函數(shù),最后出棧銷毀。doinstance(該函數(shù)將在最后的代碼中給出,主要的功能就是調(diào)用我們自己寫(xiě)的活動(dòng)計(jì)數(shù)器)我們放到最后來(lái)寫(xiě),現(xiàn)在來(lái)構(gòu)造我們的活動(dòng)計(jì)數(shù)器對(duì)象。
class TimeCount : public CActive
{
public :
static TimeCount* NewLC(); // 構(gòu)造函數(shù)
~TimeCount();
void StartL(); // 計(jì)數(shù)開(kāi)始
void ConstructL();
void RunL(); // 延時(shí)事件到達(dá)以后的處理函數(shù)
void DoCancel(); // 取消請(qǐng)求提交
void setDelayTime(int delayTime);
private:
TimeCount();
RTimer iTimer; // 定時(shí)器
int iTimeCount; // 計(jì)數(shù)器
int mTime; // 計(jì)數(shù)間隔時(shí)間 單位秒
};
TimeCount::TimeCount():CActive(0) // 這里可以設(shè)置活動(dòng)對(duì)象的優(yōu)先級(jí)
{
// 把自己加入活動(dòng)規(guī)劃器
CActiveScheduler::Add(this);
}
TimeCount* TimeCount::NewLC()
{
TimeCount* result = new (ELeave) TimeCount();
CleanupStack::PushL( result );
result->ConstructL();
return result;
}
void TimeCount::DoCancel(void)
{
iTimer.Cancel();
}
void TimeCount::setDelayTime(int mTime)
{
DelayTime = mTime;
}
TimeCount::~TimeCount()
{
Cancel();
iTimer.Close();
}
void TimeCount::StartL()
{
// 設(shè)定定時(shí)器狀態(tài)為每隔mTime秒鐘狀態(tài)完成一次
iTimer.After(iStatus, 10000 * 100 * mTime);
// 提交異步請(qǐng)求
SetActive();
}
void TimeCount::ConstructL()
{
// 初始化計(jì)數(shù)器和定時(shí)器
iTimeCount = 0;
User::LeaveIfError(iTimer.CreateLocal());
}
void TimeCount::RunL()
{
// 計(jì)數(shù)器+1以后繼續(xù)提交延時(shí)請(qǐng)求事件
printf("The Count is ->>%d", iTimeCount++);
StartL();
}
每一個(gè)活動(dòng)服務(wù)對(duì)象都有一個(gè)iStatus來(lái)標(biāo)識(shí)當(dāng)前對(duì)象的狀態(tài).在這里我們把iStatus設(shè)定為iTimer.After(iStatus, 10000 * 100 * mTime);也就是定時(shí)器定時(shí)mTime秒鐘以后iStatus發(fā)生改變,這個(gè)時(shí)候活動(dòng)規(guī)劃器會(huì)收到這個(gè)狀態(tài)的改變,從而調(diào)用相應(yīng)活動(dòng)對(duì)象的處理函數(shù),也就是RunL函數(shù).在RunL函數(shù)里面進(jìn)行計(jì)數(shù)和輸出,然后調(diào)用startL重新設(shè)置定時(shí)器和對(duì)象狀態(tài),再提交給活動(dòng)規(guī)劃器。這樣mTime秒鐘以后活動(dòng)規(guī)劃器會(huì)再次調(diào)用RunL函數(shù).一直這樣重復(fù),這樣就達(dá)到了計(jì)數(shù)器的效果。
最后我們來(lái)寫(xiě)doinstanceL函數(shù)
LOCAL_C void doInstanceL()
{
TimeCount* timeCount = TimeCount::NewLC();
// 每隔一秒鐘打印一次
TimeCount->setDelayTime(1);
TimeCount->StartL();
CActiveScheduler::Start();
CleanupStack::PopAndDestroy(1);
}
創(chuàng)建好對(duì)象以后,加上CActiveScheduler::Start()程序就開(kāi)始運(yùn)行了,這句話告訴活動(dòng)規(guī)劃器該等待對(duì)象的狀態(tài)的改變了(正常情況下,一旦CActiveScheduler::Start()之后,程序直到CActiveScheduler::Stop()才能終止運(yùn)行),在這里就是timeCount的iStatus的改變.等iStatus改變并調(diào)用了RunL以后,繼續(xù)等待iStstus的改變,這樣我們使用活動(dòng)對(duì)象的計(jì)數(shù)器就能夠通過(guò)消息驅(qū)動(dòng)運(yùn)行起來(lái)了.
這里的CActiveScheduler只管理了一個(gè)CActive對(duì)象,就是timeCount,可以用類似的方法實(shí)現(xiàn)多個(gè)CActive,并且都加入CActiveScheduler,CActiveScheduler將會(huì)等待所有加入它的CActive的狀態(tài)的改變,其中有一個(gè)的狀態(tài)改變就會(huì)去執(zhí)行對(duì)應(yīng)的活動(dòng)對(duì)象的處理函數(shù),當(dāng)狀態(tài)同時(shí)發(fā)生的時(shí)候,會(huì)通過(guò)對(duì)象的優(yōu)先級(jí)來(lái)決定先調(diào)用誰(shuí)的RunL函數(shù).CActiveScheduler也是非搶占式的,當(dāng)一個(gè)RunL函數(shù)還沒(méi)有執(zhí)行完的時(shí)候,如果另一個(gè)CActive的狀態(tài)改變,會(huì)等待RunL執(zhí)行完以后再執(zhí)行另一個(gè)CActive的處理函數(shù)(正因?yàn)檫@一點(diǎn),所以通常RunL函數(shù)不能設(shè)計(jì)為長(zhǎng)函數(shù),否則會(huì)阻塞活動(dòng)對(duì)象)。
本文在網(wǎng)上根據(jù)網(wǎng)上用人提供的原本閱讀學(xué)習(xí)而成,可算是轉(zhuǎn)載類型的。
posted @
2008-10-11 21:03 frank.sunny 閱讀(2566) |
評(píng)論 (0) |
編輯 收藏
Active Object (AO) 框架,是Symbian的基本工作部分。它是為了滿足多個(gè)任務(wù)同時(shí)執(zhí)行的要求。在 Windows/Unix 平臺(tái)上,我們可以不加思索的使用多線程來(lái)完成多任務(wù)。可是在嵌入式平臺(tái)上,系統(tǒng)的資源是有限的。比如CPU、內(nèi)存都比我們平時(shí)用的個(gè)人計(jì)算機(jī)要低。這就要求嵌入式系統(tǒng)能夠合理的使用系統(tǒng)資源。不能頻繁的切換線程或者進(jìn)程。
Symbian為這種特別需求設(shè)計(jì)了Active Object (AO)框架。AO框架是運(yùn)行于一個(gè)線程內(nèi)部的調(diào)度框架。其基本思想就是把一個(gè)單線程分為多個(gè)時(shí)間片,來(lái)運(yùn)行不同的任務(wù)。
這和多線程有很大區(qū)別。多線程之間是可以被搶占的(由操作系統(tǒng)調(diào)度),但是AO框架中的各個(gè)任務(wù)是不可被搶占的,一個(gè)任務(wù)必須完成,才能開(kāi)始下一個(gè)任務(wù)。
下面是多線程和AO框架的簡(jiǎn)單比較:
多線程 AO框架
可以被搶占 不可被搶占
上下文切換耗費(fèi)CPU時(shí)間 沒(méi)有上下文切換
由操作系統(tǒng)調(diào)度 由線程自己的AO框架調(diào)度
每個(gè)線程都有至少4K Stack. AO沒(méi)有單獨(dú)的Stack.
操作系統(tǒng)還要分配額外的資源記錄線程 只是一個(gè)Active Object.
Symbian系統(tǒng)本身使用了大量的AO框架來(lái)實(shí)現(xiàn)一些系統(tǒng)服務(wù)。這使得Symbian和其他嵌入式系統(tǒng)相比較,對(duì)系統(tǒng)資源的使用更加合理。
AO框架包括CActiveScheduler 和CActive (Active Object)。一個(gè)線程的所有的Active Object對(duì)象都被安裝在該線程的CActiveScheduler對(duì)象內(nèi).由CActiveScheduler對(duì)象監(jiān)控每個(gè)Active Object是否完成了當(dāng)前任務(wù),如果完成了,就調(diào)度下一個(gè)Active Object來(lái)執(zhí)行。CActiveScheduler根據(jù)優(yōu)先級(jí)來(lái)調(diào)度各個(gè)Active Object.
關(guān)于CActiveScheduler的創(chuàng)建和安裝,CActive的創(chuàng)建和安裝,和CActive的任務(wù)處理,可以參看 SDK 文檔。理解起來(lái)不難。下面要說(shuō)一個(gè)比較容易忽略的地方。這對(duì)理解AO框架非常重要。
創(chuàng)建調(diào)度器:
CActiveScheduler * scheduler = new (ELeave) CActiveScheduler;
CleanupStack::PushL(scheduler);
CActiveScheduler::Install(scheduler);
運(yùn)行調(diào)度器:
CActiveScheduler::Start();
停止調(diào)度器:
CActiveScheduler::Stop();
以上代碼都是運(yùn)行在一個(gè)線程中的,一般來(lái)講,一個(gè)EXE只有一個(gè)主線程.
可是如果真的有2個(gè)線程呢?
為什么在當(dāng)前線程下調(diào)用CActiveScheduler::Start(),CActiveScheduler::Stop()運(yùn)行/停止的就是當(dāng)前線程的調(diào)度器而不是另一個(gè)線程的調(diào)度器?
每個(gè)線程都有自己的CActiveScheduler,那么這個(gè)CActiveScheduler類是怎么調(diào)用CActiveScheduler::Start(),CActiveScheduler::Stop()來(lái)運(yùn)行/停止當(dāng)前的調(diào)度器的呢?
我們看到Start/Stop并沒(méi)有參數(shù).
打開(kāi)CActiveScheduler的類定義:
class CActiveScheduler : public CBase
{
public:
IMPORT_C CActiveScheduler();
IMPORT_C ~CActiveScheduler();
IMPORT_C static void Install(CActiveScheduler* aScheduler);
IMPORT_C static CActiveScheduler* Current();
IMPORT_C static void Add(CActive* anActive);
IMPORT_C static void Start();
IMPORT_C static void Stop();
IMPORT_C static TBool RunIfReady(TInt& aError, TInt aMinimumPriority);
IMPORT_C static CActiveScheduler* Replace(CActiveScheduler* aNewActiveScheduler);
IMPORT_C virtual void WaitForAnyRequest();
IMPORT_C virtual void Error(TInt anError) const;
private:
void DoStart();
void OwnedStartLoop(TInt& aRunning);
IMPORT_C virtual void OnStarting();
IMPORT_C virtual void OnStopping();
IMPORT_C virtual void Reserved_1();
IMPORT_C virtual void Reserved_2();
private:
// private interface used through by CActiveSchedulerWait objects
friend class CActiveSchedulerWait;
static void OwnedStart(CActiveSchedulerWait& aOwner);
protected:
inline TInt Level() const;
private:
TInt iLevel;
TPriQue<CActive> iActiveQ;
};
我們并沒(méi)有看到靜態(tài)的成員來(lái)表示線程,但是卻有一個(gè)static函數(shù)CActiveScheduler* Current();返回當(dāng)前線程的調(diào)度器.
現(xiàn)在猜想奧秘就在這個(gè)函數(shù)是怎么實(shí)現(xiàn)的。這個(gè)靜態(tài)的函數(shù)怎么就能得到當(dāng)前這個(gè)運(yùn)行線程的調(diào)度器,而不是別的線程的調(diào)度器。我們可以猜想,肯定是Current()內(nèi)部實(shí)現(xiàn)能取到當(dāng)前線程的標(biāo)識(shí)信息.用這個(gè)標(biāo)識(shí),靜態(tài)函數(shù)能取到這個(gè)線程的CActiveScheduler.這個(gè)具體如何實(shí)現(xiàn)呢?
答案就是:當(dāng)前線程的線程ID可以這樣得到:
創(chuàng)建一個(gè)缺省的線程對(duì)象:
RThread thread;
取得當(dāng)前線程的ID:
TThreadId threadId = thread.Id();
能得到當(dāng)前線程的threadId,當(dāng)然可以得到和當(dāng)前線程關(guān)聯(lián)的CActiveScheduler。因此以上兩個(gè)問(wèn)題也就迎刃而解了,在一個(gè)線程內(nèi)調(diào)用CActiveScheduler::Start(),CActiveScheduler::Stop()開(kāi)啟的就是當(dāng)前線程。
既然回復(fù)了上面的問(wèn)題,那么我們自然就能明確,在一個(gè)線程內(nèi)是不能通過(guò)Start和Stop函數(shù)來(lái)開(kāi)啟和停止另一個(gè)線程內(nèi)的活動(dòng)對(duì)象規(guī)劃器CActiveScheduler。
補(bǔ)充點(diǎn)其他東西:
在Symbian操作系統(tǒng)中,每個(gè)進(jìn)程都有一個(gè)或多個(gè)線程。線程是執(zhí)行的基本單位。一個(gè)進(jìn)程的主線程是在進(jìn)程啟動(dòng)時(shí)生成的。Symbian屬于搶占式多任務(wù)操作系統(tǒng),這意味著每個(gè)線程都有自己的執(zhí)行時(shí)間,直到系統(tǒng)將CPU使用權(quán)給予其他線程。當(dāng)系統(tǒng)調(diào)度時(shí),具有最高優(yōu)先權(quán)的線程將首先獲得執(zhí)行。
進(jìn)程邊界是受內(nèi)存保護(hù)的。所有的用戶進(jìn)程都有自己的內(nèi)存地址空間,同一進(jìn)程中的所有線程共享這一空間,用戶進(jìn)程不能直接訪問(wèn)其他進(jìn)程的地址空間。
每個(gè)線程都有它自己的stack和heap,這里heap可以是私有的,也可以被其他線程共享。應(yīng)用程序框架生成并安裝了一個(gè)active scheduler,并且為主線程準(zhǔn)備了清除棧。如果沒(méi)有使用框架(如編寫(xiě)exe程序)那就要手動(dòng)生成這些了。
Symbian操作系統(tǒng)專為單線程應(yīng)用優(yōu)化,因此強(qiáng)烈推薦使用“活動(dòng)對(duì)象”代替多線程。
posted @
2008-10-11 20:34 frank.sunny 閱讀(2693) |
評(píng)論 (2) |
編輯 收藏
如何在C++中調(diào)用C的代碼
以前曾經(jīng)總結(jié)過(guò)一篇(http://www.shnenglu.com/franksunny/archive/2007/11/29/37510.html),關(guān)于在C中如何調(diào)用C++的代碼,當(dāng)時(shí)并未做完全的展開(kāi),只是簡(jiǎn)單的做了下調(diào)試,最近看到一個(gè)題目要求實(shí)現(xiàn)C和C++中代碼的互相調(diào)用,其結(jié)果雖然都是通過(guò)extern “C”來(lái)實(shí)現(xiàn),但是具體還是有些差別的。
先對(duì)C中調(diào)用C++代碼作個(gè)簡(jiǎn)單回顧:
1、 對(duì)于C++中非類的成員函數(shù),可以簡(jiǎn)單的在函數(shù)聲明前面加extern “C”,通常函數(shù)聲明位于頭文件中,當(dāng)然也可以將聲明和函數(shù)定義一起放在cpp中,在沒(méi)有聲明的情況下,直接在定義前添加extern “C”也可
2、 對(duì)于C++類的成員函數(shù),則需要另外做一個(gè)cpp文件,將需要調(diào)用的函數(shù)進(jìn)行包裝。
以上兩項(xiàng)的實(shí)例參看前面C中如何調(diào)用C++代碼的文章。
要實(shí)現(xiàn)C++中調(diào)用C的代碼,具體操作:
對(duì)于C中的函數(shù)代碼,要么將C代碼的頭文件進(jìn)行修改,在其被含入C++代碼時(shí)在聲明中加入extern “C”或者在C++代碼中重新聲明一下C函數(shù),重新聲明時(shí)添加上extern “C”頭。
通過(guò)以上的說(shuō)明,我明白一點(diǎn),那就是加extern “C”頭一定是加在C++的代碼文件中才能起作用的。
下面分析一下這個(gè)現(xiàn)象的實(shí)質(zhì)原因:
C編譯器編譯函數(shù)時(shí)不帶函數(shù)的類型信息,只包含函數(shù)符號(hào)名字,如C編譯器把函數(shù)int a(float x)編譯成類似_a這樣的符號(hào),C連接器只要找到了調(diào)用函數(shù)的符號(hào),就可以連接成功,它假設(shè)參數(shù)類型信息是正確的,這是C編譯連接器的缺點(diǎn)。而C++編譯器為了實(shí)現(xiàn)函數(shù)重載,編譯時(shí)會(huì)帶上函數(shù)的類型信息,如他把上面的a函數(shù)可能編譯成_a_float這樣的符號(hào)為了實(shí)現(xiàn)重載,注意它還是沒(méi)有帶返回值得信息,這也是為什么C++不支持采用函數(shù)返回值來(lái)區(qū)別函數(shù)重載的原因之一,當(dāng)然,函數(shù)的使用者對(duì)函數(shù)返回值的處理方式(如忽略)也是重要原因。
基于以上,C調(diào)用C++,首先需要用封裝函數(shù)把對(duì)C++的類等的調(diào)用封裝成C函數(shù)以便C調(diào)用,于是extern "C"的作用是:讓編譯器知道這件事,然后以C語(yǔ)言的方式編譯和連接封裝函數(shù)(通常是把封裝函數(shù)用C++編譯器按C++方式編譯,用了extern "C" 后,編譯器便依C的方式編譯封裝接口,當(dāng)然接口函數(shù)里面的C++語(yǔ)法還是按C++方式編譯;對(duì)于C語(yǔ)言部分--調(diào)用者,還是按C語(yǔ)言編譯;分別對(duì)C++接口部分和C部分編譯后,再連接就可以實(shí)現(xiàn)C調(diào)用C++了)。相反,C++調(diào)用C函數(shù),extern "C" 的作用是:讓C++連接器找調(diào)用函數(shù)的符號(hào)時(shí)采用C的方式,即使用_a而不是_a_float來(lái)找調(diào)用函數(shù)。
具體示例請(qǐng)見(jiàn)http://www.shnenglu.com/Files/franksunny/CCallCpp.rar
注:如果你用VC6.0編譯附件時(shí)遇到類似“fatal error C1010: unexpected end of file while looking for precompiled header directive”報(bào)錯(cuò)的話,請(qǐng)將bb.c文件做如下處理右鍵點(diǎn)擊項(xiàng)目工程中的該文件,選擇setting,在c/c++欄,選擇PreCompiled headers,然后設(shè)置第一選項(xiàng),選擇不使用預(yù)編譯頭。
posted @
2008-10-10 17:54 frank.sunny 閱讀(8989) |
評(píng)論 (1) |
編輯 收藏
摘要:
活動(dòng)對(duì)象框架原理
一、概述:
Symbian OS是一個(gè)多任務(wù)的操作系統(tǒng),那么為了實(shí)現(xiàn)多任務(wù),同時(shí)使系統(tǒng)能夠快速響應(yīng),高效的進(jìn)行事件處理,并減輕應(yīng)用程序員的工作負(fù)擔(dān)(申請(qǐng)大多數(shù)耗時(shí)的操作(例如文件系統(tǒng))由服務(wù)提供器來(lái)完成,服務(wù)提供器完成程序員提交的請(qǐng)求后,將會(huì)返回給程序員一個(gè)成功或失敗的信號(hào)。),Symbian OS特意引入了活動(dòng)對(duì)象的概念。
服務(wù)提供器API...
閱讀全文
posted @
2008-10-09 20:42 frank.sunny 閱讀(1826) |
評(píng)論 (0) |
編輯 收藏
這種在Symbian C/S架構(gòu)中,服務(wù)器程序與客戶UI進(jìn)程主動(dòng)通信中用的比較多。
對(duì)于在往UI框架應(yīng)用程序發(fā)送消息,可以通過(guò)Symbian OS的Application Architecture Services可以進(jìn)行應(yīng)用程序間的通信,主要用到的類包括:TApaTaskList和TApaTask。
TApaTaskList:用于訪問(wèn)設(shè)備中正在運(yùn)行的任務(wù)(假如有些任務(wù)隱藏了的話,那么通過(guò)這種方法也無(wú)法進(jìn)行訪問(wèn))。
TApaTask:表示設(shè)備中某個(gè)運(yùn)行的任務(wù),通過(guò)與程序關(guān)聯(lián)的窗口組(window group)標(biāo)識(shí)。
具體的解決方案:
發(fā)送消息端:使用TApaTaskList找到等待接收消息的任務(wù),TApaTaskList::FindApp()提供了兩個(gè)重載版本,可以使用程序的標(biāo)題,也可以使用程序的UID進(jìn)行查找。獲得需要發(fā)消息的任務(wù)后就可以通過(guò)TApaTask:: SendMessage()發(fā)送消息了,它有兩個(gè)參數(shù),第一個(gè)參數(shù)用于標(biāo)識(shí)消息,第二個(gè)參數(shù)是一個(gè)描述符的引用,可以用來(lái)提供不同消息時(shí)附加的具體信息。
TUid uid( TUid::Uid( 0x0116C9D3 ) );
TApaTaskList taskList( iCoeEnv->WsSession() );
TApaTask task = taskList.FindApp(uid );
if( task.Exists() ) //判斷任務(wù)是否正在運(yùn)行
{
LIT8( KTestMsg, "CustomMessage" );
TUid msgUid( TUid::Uid( 1 ) );
task.SendMessage( uid, KTestMsg );
}
接收消息端可以使用如下兩種方案:
第一種方案:由于MCoeMessageObserver是處理來(lái)自窗口服務(wù)器消息的接口類,而CEikAppUi已經(jīng)繼承自MCoeMessageObserver,所以我們只需要在自己的UI類中重現(xiàn)實(shí)現(xiàn)MCoeMessageObserver的唯一成員函數(shù)HandleMessageL()用來(lái)處理接收到的消息即可,代碼如下:
MCoeMessageObserver::TMessageResponse CXXXAppUi::HandleMessageL(TUint32 aClientHandleOfTargetWindowGroup, TUid aMessageUid, const TDesC8& aMessageParameters)
{
_LIT( KFormatStr, "%x" );
TBuf<32> bufUid;
TBuf<32> bufPara;
bufUid.AppendFormat( KFormatStr, aMessageUid.iUid );
bufPara.Copy( aMessageParameters );
iEikonEnv->InfoWinL( bufUid, bufPara );
return MCoeMessageObserver::EMessageHandled;
}
第二種方案:由于TApaTask::SendMessage()發(fā)送的消息可以被CEikAppUI的成員函數(shù)ProcessMessageL()攔截并處理,不過(guò)必須在沒(méi)有重載HandleMessageL()函數(shù)的前提下,而且函數(shù)ProcessMessageL()只負(fù)責(zé)攔截消息標(biāo)識(shí)為KUidApaMessageSwitchOpenFileValue和KUidApaMessageSwitchCreateFileValue的這兩個(gè)消息,其它標(biāo)識(shí)值的消息不會(huì)被傳到ProcessMessageL()中,所以這種方案?jìng)€(gè)人覺(jué)得很受限制,不自由,還是采用第一種方案好,具體代碼代碼如下:
//發(fā)送:
TUid uid( TUid::Uid( 0x0116C9D3 ) );
TApaTaskList taskList( iCoeEnv->WsSession() );
TApaTask task = taskList.FindApp(uid );
if( task.Exists() ) //判斷任務(wù)是否正在運(yùn)行
{
LIT8( KTestMsg, "CustomMessage" );
//這里的Uid不能使用自定義的,而且只有系統(tǒng)提供的兩個(gè)
TUid msgUid( TUid::Uid(KUidApaMessageSwitchCreateFileValue) );
task.SendMessage( uid, KTestMsg );
}
//接收:
void CXXXAppUi::ProcessMessageL(TUid aUid,const TDesC8& aParams)
{
RFileLogger iLog;
iLog.Connect();
iLog.CreateLog(_L("tb"), _L("UpdateListener2.txt"), EFileLoggingModeOverwrite);
iLog.Write(_L("smms appui"));
if (aUid.iUid == KUidApaMessageSwitchCreateFileValue)
{
TBuf<256> buf;
buf.Copy(aParams);
iLog.Write(aParams);
BringMeToFront();
ShowCreateFile(buf,CFileMonitorEngine::EImageType);
}
else
{
CAknViewAppUi::ProcessMessageL(aUid,aParams);
}
iLog.Close();
}
明天就是中秋了,恭祝大家中秋節(jié)快樂(lè)
posted @
2008-09-13 07:46 frank.sunny 閱讀(2081) |
評(píng)論 (1) |
編輯 收藏
摘要:
關(guān)于vCard和Symbian上的操作
前陣子關(guān)于Symbian通訊錄操作的時(shí)候曾提到vCard,但是由于當(dāng)時(shí)項(xiàng)目比較緊,所以也沒(méi)有時(shí)間整理,今天特意抽了點(diǎn)時(shí)間小試了一下,發(fā)現(xiàn)很多手機(jī)(我試了下索愛(ài)的和諾基亞的)如果選中通訊錄中的記錄發(fā)送聯(lián)系人或者發(fā)送名片之類的操作,就是會(huì)以vcf文件格式進(jìn)行發(fā)送。不過(guò)手機(jī)上的vcf文件通常是用UTF-8編碼的,所以雖然可以用ou...
閱讀全文
posted @
2008-09-13 07:20 frank.sunny 閱讀(3716) |
評(píng)論 (0) |
編輯 收藏
摘要: Symbian OS平臺(tái)簡(jiǎn)體漢字編程編碼處理
相信大家都在處理symbian中文顯示的時(shí)候遇到了編碼的問(wèn)題,我現(xiàn)在就給總結(jié)一下這種問(wèn)題的解決方法:
字符串編碼中文表示常用的有:GB2312,GBK,Unicode,UTF-8
其中GBK是GB2312的超集,也就是涵蓋了GB2312編碼的所有內(nèi)容;
UTF-8是Unicode的在網(wǎng)絡(luò)傳輸中的一種編碼格式。
如果我們使用...
閱讀全文
posted @
2008-09-10 20:11 frank.sunny 閱讀(4125) |
評(píng)論 (1) |
編輯 收藏
摘要: Symbian OS中的消息存儲(chǔ)與常用操作
說(shuō)明:本文前面消息的基本知識(shí)主要參考《Series60應(yīng)用程序開(kāi)發(fā)》中的有關(guān)內(nèi)容,后面是前段做MTM開(kāi)發(fā)中用到的代碼。
一、消息存儲(chǔ)基本知識(shí)
Symbian OS提供的消息傳送架構(gòu)基于Client/Server機(jī)制,服務(wù)器負(fù)責(zé)管理手機(jī)上的各種消息,在進(jìn)行消息相關(guān)操作之前我們需要了解Symbian OS是如何組織和存儲(chǔ)消息的。
手機(jī)中的各種消息...
閱讀全文
posted @
2008-07-30 21:04 frank.sunny 閱讀(3258) |
評(píng)論 (2) |
編輯 收藏
摘要:
Symbian OS應(yīng)用開(kāi)發(fā)學(xué)習(xí)筆記之通訊錄(電話薄Contacts)
Symbian OS通訊錄模型
Symbian OS手機(jī)的通訊錄采用文件方式存儲(chǔ),用symbian自己的說(shuō)法就是通訊錄數(shù)據(jù)庫(kù)。每個(gè)Symbian OS手機(jī)都有一個(gè)默認(rèn)的通訊錄數(shù)據(jù)庫(kù),這個(gè)通訊錄數(shù)據(jù)庫(kù)在2nd和3rd兩個(gè)版本手機(jī)中的位置是不同的,前者是c:\ system\data\Conta...
閱讀全文
posted @
2008-06-27 08:05 frank.sunny 閱讀(6442) |
評(píng)論 (8) |
編輯 收藏
今天接到電話面試,被問(wèn)到幾個(gè)問(wèn)題,汗顏之余,小結(jié)一下
1、 多態(tài)是如何實(shí)現(xiàn)綁定的
多態(tài)的綁定可以分為運(yùn)行是多態(tài)和編譯時(shí)多態(tài)
● 編譯時(shí)的多態(tài)性
編譯時(shí)的多態(tài)性是通過(guò)重載來(lái)實(shí)現(xiàn)的。對(duì)于非虛的成員來(lái)說(shuō),系統(tǒng)在編譯時(shí),根據(jù)傳遞的參數(shù)、返回的類型等信息決定實(shí)現(xiàn)何種操作。
● 運(yùn)行時(shí)的多態(tài)性
運(yùn)行時(shí)的多態(tài)性就是指直到系統(tǒng)運(yùn)行時(shí),才根據(jù)實(shí)際情況決定實(shí)現(xiàn)何種操作。C#中,運(yùn)行時(shí)的多態(tài)性通過(guò)虛成員實(shí)現(xiàn)。
編譯時(shí)的多態(tài)性為我們提供了運(yùn)行速度快的特點(diǎn),而運(yùn)行時(shí)的多態(tài)性則帶來(lái)了高度靈活和抽象的特點(diǎn)。
今天才正式弄清楚原來(lái)虛函數(shù)是可以實(shí)現(xiàn)運(yùn)行時(shí)多態(tài)的,以前只知道虛函數(shù)可以使得基類對(duì)象的的方法調(diào)用派生類的方法。
2、 析構(gòu)函數(shù)是虛函數(shù)的優(yōu)點(diǎn)是什么
用C++開(kāi)發(fā)的時(shí)候,用來(lái)做基類的類的析構(gòu)函數(shù)一般都是虛函數(shù)。可是,為什么要這樣做呢?下面用一個(gè)小例子來(lái)說(shuō)明:
有下面的兩個(gè)類:
class ClxBase
{
public:
ClxBase() {};
virtual ~ClxBase() {};
virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};
class ClxDerived : public ClxBase
{
public:
ClxDerived() {};
~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };
void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
};
代碼
ClxBase *pTest = new ClxDerived;
pTest->DoSomething();
delete pTest;
輸出結(jié)果是:
Do something in class ClxDerived!
Output from the destructor of class ClxDerived!
這個(gè)很簡(jiǎn)單,非常好理解。
但是,如果把類ClxBase析構(gòu)函數(shù)前的virtual去掉,那輸出結(jié)果就是下面的樣子了:
Do something in class ClxDerived!
也就是說(shuō),類ClxDerived的析構(gòu)函數(shù)根本沒(méi)有被調(diào)用!一般情況下類的析構(gòu)函數(shù)里面都是釋放內(nèi)存資源,而析構(gòu)函數(shù)不被調(diào)用的話就會(huì)造成內(nèi)存泄漏。我想所有的C++程序員都知道這樣的危險(xiǎn)性。當(dāng)然,如果在析構(gòu)函數(shù)中做了其他工作的話,那你的所有努力也都是白費(fèi)力氣。
所以,文章開(kāi)頭的那個(gè)問(wèn)題的答案就是--這樣做是為了當(dāng)用一個(gè)基類的指針刪除一個(gè)派生類的對(duì)象時(shí),派生類的析構(gòu)函數(shù)會(huì)被調(diào)用。
當(dāng)然,并不是要把所有類的析構(gòu)函數(shù)都寫(xiě)成虛函數(shù)。因?yàn)楫?dāng)類里面有虛函數(shù)的時(shí)候,編譯器會(huì)給類添加一個(gè)虛函數(shù)表,里面來(lái)存放虛函數(shù)指針,這樣就會(huì)增加類的存儲(chǔ)空間。所以,只有當(dāng)一個(gè)類被用來(lái)作為基類的時(shí)候,才把析構(gòu)函數(shù)寫(xiě)成虛函數(shù)。
說(shuō)實(shí)話,這個(gè)也是今天才深刻認(rèn)識(shí)到的。
當(dāng)然還問(wèn)到很多數(shù)據(jù)結(jié)構(gòu)和算法方面(空間復(fù)雜度和時(shí)間復(fù)雜度之類的東東,說(shuō)真的也是基礎(chǔ)性的)的問(wèn)題,至于那些東西,自己說(shuō)實(shí)話拋開(kāi)沒(méi)用他們已經(jīng)很長(zhǎng)時(shí)間了,真可以說(shuō)忘的差不多了,考這種真的很怕,也怪平時(shí)沒(méi)怎么用到。不知道大家用的多不?
好久沒(méi)有正式參加過(guò)面試了,今天突然來(lái)一次覺(jué)得自己基礎(chǔ)還是不夠扎實(shí)。
posted @
2008-05-19 20:30 frank.sunny 閱讀(18151) |
評(píng)論 (12) |
編輯 收藏