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

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

call與callback

回調(diào)機(jī)制

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

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

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

何時(shí)需要 Callback ?

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

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

這時(shí),我們將這個(gè)函數(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);

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

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

        printf("%d%% \n", 100*copied / total);//按百分比顯示拷貝進(jìn)度
        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ù)時(shí),總是會(huì)透?jìng)饕粋€(gè)void參數(shù),指向一個(gè)上下文對(duì)象。
"透?jìng)?:透明的,不關(guān)心其類型與內(nèi)容,什么樣的進(jìn)來(lái)、什么樣的出去。。。void

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

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


上下文

然而,在回調(diào)函數(shù)的參數(shù)里,并沒(méi)有源文件名和目標(biāo)文件名。。。也就是說(shuō),無(wú)法得知當(dāng)前正在拷貝的哪個(gè)文件。。。

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

CopyFileEx function

CopyProgressRoutine callback function

上下文對(duì)象:該對(duì)象攜帶了所有必要的上下文信息。。。
可以為任意類型的數(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)換上下文對(duì)象
        Context* ctx = (Context*)lpData;

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

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

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

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

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

    //const char* source = "F:\\迅雷下載\\taxt/123.mkv";
    //const char* dst = "F:\\迅雷下載\\taxt/出租車司機(jī).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;
}

??我的目標(biāo)是:someday,即便你花錢看我的文章,也會(huì)覺(jué)得心滿意足


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容