2014-04-04 19 views
1

我正在實現一個庫,需要根據不同的原因調用用戶代碼。例如,假設我們調用用戶代碼來加密某些東西(我們讓用戶這樣做有兩個原因:也許他會利用算法的硬件實現或者他可能不想實現密碼學,只是在調用的時刻返回字符串)。C庫調用用戶代碼(函數指針vs外部符號)

更優雅讓用戶給我一個函數指針的「加密」功能,例如

void (* encrypt_f)(void *ctx, void *dst, void *src, size_t n); 
void (* decrypt_f)(void *ctx, void *dst, void *src, size_t n); 
void (* set_key_f)(void *ctx, void *key, size_t n); 

struct cipher_interface 
{ 
    encrypt_f encrypt; 
    decrypt_f decrypt; 
    set_key_f set_key;` 
}; 

,我會使用類似呼叫從庫中的用戶代碼:

struct lib_ctx 
{ 
    void *usr_ctx; 
    struct cipher_interface *usr_itf; 
    /* ... */ 
}; 

void lib_function(struct lib_ctx *ctx, ...) 
{ 
    /* ... */ 
    if (ctx->usr_itf->encrypt != NULL) 
     ctx->usr_itf->encrypt(ctx->usr_ctx, ...); 
} 

有了上述解決方案的用戶,如果他不想實現某個功能,他可以在函數指針中存儲一個空指針。

另一種解決方案是簡單地留下一些未解決的符號功能的用戶必須執行:

void usr_encrypt(void *ctx, void *dst, void *src, size_t n); 
void usr_decrypt(void *ctx, void *dst, void *src, size_t n); 
void usr_set_key(void *ctx, void *key, size_t n); 

struct lib_ctx 
{ 
    void *usr_ctx; 
    /* ... */ 
}; 

void lib_function(struct lib_ctx *ctx, ...) 
{ 
    /* ... */ 
    usr_encrypt(ctx->usr_ctx, ...); 
} 

在第二個方案中,如果用戶不想使用某個功能,它至少必須定義空函數來解析符號。

void usr_encrypt(...) {} 

我的圖書館是一個網絡協議庫,並有很多的電話像這裏提出的那些用戶代碼(例如hdlc_connection_indication通知有關HDLC連接成功,用戶等)

它是什麼這種情況下的最佳方法?

+0

是的,可能使用函數指針。給他們每個人一個客戶端數據。用客戶端數據註冊客戶端功能。 –

回答

1

我認爲前面的方法,通過代碼處理「作爲數據」的顯式函數指針是最好的。

後一種方法使得很難在同一個程序中有相同庫的用戶(可能用於不同的上下文),因此很難處理。

例如,考慮加密網絡和磁盤流量,這些流量可能位於應用程序內部的兩個完全不同的子系統中,但他們可能仍然希望使用相同的庫服務。用一個明確的「背景」傳遞給圖書館,這是無痛的;與鏈接級別的符號魔術幾乎是不可能的。

0

第一個解決方案當然更靈活,但第二個更有效一些,因爲所有的調用都是直接的,也是因爲它沒有包含調用之前的所有空指針檢查。 我不確定我將採取的路徑:/