callback function(回調(diào)函數(shù))

簡單的說,我們調(diào)用別人的API叫call,調(diào)用的第三方api調(diào)用我們的函數(shù)叫回調(diào)(callback)

call與callback

回調(diào)機制

比如,要拷貝一個文件,將1.pdf拷貝成1_copy.pdf。。。

方法:調(diào)用Windows API(系統(tǒng)函數(shù)庫)

里面有一個CopyFile函數(shù)
CopyFile("1.pdf", "2.pdf" ... );
這種調(diào)用就叫Call,即,調(diào)用別人的函數(shù)

何時需要 Callback ?

考慮:拷貝一個很大的文件(比如,1G的視頻文件)。。。。
這個拷貝過程需要一段時間。。。
如果用CopyFile(…),則需要默默等待、直到它完成。。。
缺點:用戶體驗差,缺少交互性
這時候,我們希望增加交互性:顯示拷貝的進度這意味著,我們希望系統(tǒng)在拷貝文件的時候,能夠通知我們的應用程序。。。

比如,我們提供一個函數(shù)
void CopyProgress(int total, int copied)
{
}
我們希望: 系統(tǒng)能夠時不時的調(diào)用我們的這個函數(shù),將total/copied數(shù)據(jù)通知給我們。。。

這時,我們將這個函數(shù)的地址作為參數(shù)傳給API即可
CopyFileEx(source, dst, &CopyProgress, NULL, NULL, 0);

示例代碼:

#include<windows.h>
#include<stdio.h>

// 將LARGE_INTTEGER類型轉(zhuǎn)成unsigned long long
unsigned long long translate(LARGE_INTEGER num)
{
    unsigned long long result = num.HighPart;
    result <<= 32;
    result += num.LowPart;
    return result;
}

// 回調(diào)函數(shù)
// 注:要求將此函數(shù)用關(guān)鍵字CALLBACK修飾(這是Windows API的要求)
DWORD CALLBACK CopyProgress(
         LARGE_INTEGER TotalFileSize,
         LARGE_INTEGER TotalBytesTransferred,
         LARGE_INTEGER StreamSize,
         LARGE_INTEGER StreamBytesTransferred,
         DWORD         dwStreamNumber,
         DWORD         dwCallbackReason,
         HANDLE        hSourceFile,
         HANDLE        hDestinationFile,
         LPVOID        lpData)
{   
        //文件的總字節(jié)數(shù) TotalFileSize
        unsigned long long total = translate(TotalFileSize);

        //已完成的字節(jié)數(shù) TotalBytesTransferred
        unsigned long long copied = translate(TotalBytesTransferred);

        //打印進度
        //printf("進度:%I64d / %I64d \n", copied, total);// 64位整數(shù)用 %I64d

        //printf("進度: %d / %d \n", (int)copied, (int)total); // 文件大小于2G時,可以轉(zhuǎn)成int

        printf("%d%% \n", 100*copied / total);//按百分比顯示拷貝進度
        return PROGRESS_CONTINUE;
}
int main()
{
    const char* source = "c:\\test\\2.rmvb";
    const char* dst    = "c:\\test\\2_copy.rmvb";

    printf("start copy ...\n");

    // 將函數(shù)指針傳給CopyFileEx
    BOOL result = CopyFileEx(source, dst, &CopyProgress, NULL, NULL, 0);

    printf("operation done : %s \n", result ? "success" : "failed");

    return 0;
}

2.回調(diào)函數(shù)中的上下文

使用回調(diào)函數(shù)時,總是會透傳一個void參數(shù),指向一個上下文對象。
"透傳":透明的,不關(guān)心其類型與內(nèi)容,什么樣的進來、什么樣的出去。。。void

注意:上下文對象的生命期在回調(diào)函數(shù)被觸發(fā)時,該上下文對象必須是有效的。。

我們希望在函數(shù)回調(diào)時顯示其他信息,文件名......


上下文

然而,在回調(diào)函數(shù)的參數(shù)里,并沒有源文件名和目標文件名。。。也就是說,無法得知當前正在拷貝的哪個文件。。。

在回調(diào)函數(shù)中參數(shù) “ lpData”即上下文,類型為“ LPVOID”也就是void*類型,

CopyFileEx function

CopyProgressRoutine callback function

上下文對象:該對象攜帶了所有必要的上下文信息。。。
可以為任意類型的數(shù)據(jù),完全有用戶自己決定。。。
比如:

struct Context
{
char username[32];
char source[128];
char dst[128];
};

示例代碼:

#include<windows.h>
#include<stdio.h>
#include<string.h>

struct Context {
    char username[32];
    char source[128];
    char dst[128];
};

// 將LARGE_INTTEGER類型轉(zhuǎn)成unsigned long long
unsigned long long translate(LARGE_INTEGER num)
{
    unsigned long long result = num.HighPart;
    result <<= 32;
    result += num.LowPart;
    return result;
}

// 回調(diào)函數(shù)
// 注:要求將此函數(shù)用關(guān)鍵字CALLBACK修飾(這是Windows API的要求)
DWORD CALLBACK CopyProgress(
         LARGE_INTEGER TotalFileSize,
         LARGE_INTEGER TotalBytesTransferred,
         LARGE_INTEGER StreamSize,
         LARGE_INTEGER StreamBytesTransferred,
         DWORD         dwStreamNumber,
         DWORD         dwCallbackReason,
         HANDLE        hSourceFile,
         HANDLE        hDestinationFile,
         LPVOID        lpData)
{   
        //文件的總字節(jié)數(shù) TotalFileSize
        unsigned long long total = translate(TotalFileSize);

        //已完成的字節(jié)數(shù) TotalBytesTransferred
        unsigned long long copied = translate(TotalBytesTransferred);

        //轉(zhuǎn)換上下文對象
        Context* ctx = (Context*)lpData;

        //打印進度
        //printf("進度:%I64d / %I64d \n", copied, total);// 64位整數(shù)用 %I64d

        //printf("進度: %d / %d \n", (int)copied, (int)total); // 文件大小于2G時,可以轉(zhuǎn)成int

        printf("[%s]\t%s\t->\t%s\t%d%% \n",ctx->username,ctx->source,ctx->dst,(int)100*copied / total);//按百分比顯示拷貝進度
        return PROGRESS_CONTINUE;
}

int main() {
    //定義上下文對象
    Context con;
    strcpy_s(con.username, "NiceBlueChai");
    strcpy_s(con.source, "E:\\與孩子一起學編程(中文完整版).pdf");
    strcpy_s(con.dst, "e:\\1234.pdf");

    const char* source = "E:/與孩子一起學編程(中文完整版).pdf";
    const char* dst = "e:/1234.pdf";

    //const char* source = "F:\\迅雷下載\\taxt/123.mkv";
    //const char* dst = "F:\\迅雷下載\\taxt/出租車司機.mkv";

        printf("start copy...\n");
        system("color 70");
        BOOL result = CopyFileEx(source, dst, &CopyProgress,&con,NULL,0);

        printf("operation done:%s\n", result ? "success" : "filed");
        getchar();
    return 0;
}

??我的目標是:someday,即便你花錢看我的文章,也會覺得心滿意足


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,237評論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,957評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,248評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,356評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,081評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,485評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,534評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,720評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,263評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,025評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,204評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,787評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,461評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,874評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,105評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,945評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,205評論 2 375

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,807評論 18 139
  • 前言 人生苦多,快來 Kotlin ,快速學習Kotlin! 什么是Kotlin? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,249評論 9 118
  • 一、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運行的地址不確定 關(guān)于...
    SeanCST閱讀 7,859評論 0 27
  • 第二封詩 通俗的段落被敷衍著拋棄 迷離且密集的人群保持沉默 你說 入睡前懊惱悠忽剎那 我說...
    賈方舟閱讀 186評論 0 1
  • 目錄結(jié)構(gòu) Requests-2.18.4的源碼目錄結(jié)構(gòu)如下所示: 其中核心部分無疑是requests目錄了。 代碼...
    發(fā)條蛙閱讀 249評論 0 0