利用c语言结构体和union实现类似c++的public,private的实现
最近在看strongswan源代碼,看到strongswan的代碼框架很有意思,用C語(yǔ)言實(shí)現(xiàn)類(lèi)的思想。當(dāng)我們編寫(xiě)完一個(gè)模塊,我們需要提供的是H的文件給其他模塊使用,我們希望H文件中就只能包含一些公有函數(shù),和一些類(lèi)型的申明,不希望其他模塊篡改我們C文件私有的變量,訪問(wèn)我們的私有方法,strongswan的代碼實(shí)現(xiàn)這種類(lèi)思想,舉個(gè)簡(jiǎn)單的例子,如圖:
比如左側(cè)C文件是一個(gè)主程序,可以調(diào)用模塊1和模塊2提供的公有函數(shù),這些函數(shù)在相應(yīng)模塊H文件中,但是也僅僅只能調(diào)用這些公有函數(shù),模塊的C文件中的私有函數(shù)和私有變量無(wú)法訪問(wèn)。(當(dāng)然如果模塊2想調(diào)用模塊1的函數(shù)也類(lèi)似,模塊2的C文件包含模塊1的H文件,圖沒(méi)標(biāo)識(shí))
可以先看看strongswan中模塊C文件中的一部分代碼,主要為了顯示這種框架,基本strongswan每個(gè)模塊都是這種格式,包含如下:
1.包含自己模塊的頭文件,頭文件中有模塊公有的結(jié)構(gòu)體定義。
2.模塊C文件定義私有結(jié)構(gòu)體,私有結(jié)構(gòu)體包含一個(gè)公有結(jié)構(gòu)體變量,以及包含自己的私有方法或者變量。
3.模塊C文件定義了公有方法METHOD(當(dāng)然也包括私有方法,不過(guò)先關(guān)注公有方法)。
4.模塊C文件定義了如何創(chuàng)建公有結(jié)構(gòu)體的函數(shù)并返回公有結(jié)構(gòu)體的指針。
??? #include "crypto_factory.h"
??? ?
??? struct private_crypto_factory_t {
??????????? crypto_factory_t public;
??????????? /*private method or value*/
??? }
??? ?
??? METHOD(crypto_factory_t, create_verify_enumerator, enumerator_t*,
??????????? private_crypto_factory_t *this, transform_type_t type)
??? {
??????????? /*public method code*/
??? ?
??? }
??? ?
??? crypto_factory_t *crypto_factory_create() {
??? ?
??????????? /*create public struct*/
??? ?
??? }
H文件摘取一部分代碼,主要顯示這種格式,如圖:
??? struct crypto_factory_t {
??? ?
??????????? /*一堆公有函數(shù)指針*/
??? ?
??? }
??? crypto_factory_t *crypto_factory_create();
而其中METHOD的方法的宏定義如下:
??? #define METHOD(iface, name, ret, this, ...) \
??????????? static ret name(union {iface *_public; this;} \
??????????? __attribute__((transparent_union)), ##__VA_ARGS__); \
??????????? static typeof(name) *_##name = (typeof(name)*)name; \
??????????? static ret name(this, ##__VA_ARGS__)
如果看到這個(gè)宏定義會(huì)有點(diǎn)暈,聽(tīng)我一一講來(lái),當(dāng)然我自己編寫(xiě)了個(gè)簡(jiǎn)單例子可以直接理解這種框架思想,可以直接跳到例子看。
從這個(gè)宏定義來(lái)說(shuō):
1.先看第一句話,static ret name(union {iface *_public; this;} __attribute__((transparent_union)), ##__VA_ARGS__);
這個(gè)的意思是向編譯器提供一個(gè)函數(shù)原型,而函數(shù)的第一個(gè)參數(shù)是一個(gè)透明聯(lián)合類(lèi)型,這個(gè)是用來(lái)干嘛呢,正常函數(shù)定義時(shí)候需要指定參數(shù)的類(lèi)型,而設(shè)置成透明聯(lián)合類(lèi)型,可以讓函數(shù)接受不同類(lèi)型參數(shù)。
舉個(gè)例子:已經(jīng)定義了void func_a(int a)函數(shù),功能是打印a的值,如果你想這個(gè)功能也接受類(lèi)型float b,而你又不想重新定義另個(gè)函數(shù),這時(shí)候可以使用透明聯(lián)合類(lèi)型,函數(shù)變成:void func_a(union { int a;float b;}__attribute__((transparent_union)))。
再看看第二個(gè)參數(shù),是##__VA_ARGS__,這個(gè)是一個(gè)宏,可以接受可變數(shù)目的參數(shù),代表就是METHOD最后面的省略號(hào)(可變參數(shù)),而加上##表示如果沒(méi)有可變參數(shù)時(shí)候,去掉前面的逗號(hào),如它允許這樣調(diào)用,name(this, a, b, c),也允許只調(diào)用name(this)這樣。
2.再看第二句話,先定義了一個(gè)函數(shù)指針,*_name,它的類(lèi)型跟第一句話我們定義的一樣,并且把我們第一句話函數(shù)定義的指針變量賦給它。可以簡(jiǎn)單理解為,第一句話我們定義了一個(gè)int *a,然后我們又定義了一個(gè)int *_a,并且把a(bǔ)的值賦給_a,_a=a。
3.最后一句話就很普通了,就是定義一個(gè)函數(shù)了。
第一看在想為什么要搞得這么復(fù)雜?后來(lái)慢慢理解了它的思想,這邊可以先看看一個(gè)簡(jiǎn)單的例子,用這種框架思想寫(xiě)了一個(gè)簡(jiǎn)單的模塊,我把METHOD相應(yīng)的宏展開(kāi)了,方便理解。
C文件,print_module.c
??? #include <stdio.h>
??? #include <stdlib.h>
??? #include "print_module.h"
??? ?
??? typedef struct private private;
??? struct private {
?? ??? ?public p;
?? ??? ?int private_v1;
??? };
??? ?
??? typedef union u_t
??? {
??????? public *p1;
??????? private *p2;
??? } u_t __attribute__((__transparent_union__));
??? ?
??? static void print_value(u_t u);
??? static typeof(print_value) *_print_value = (typeof(print_value)*)print_value;
??? static void print_value(private *p)
??? {
?? ??? ?printf("%d\n",p->private_v1);
?? ??? ?
??? }
??? ?
??? static void destory(u_t u);
??? static typeof(destory) *_destory = (typeof(destory)*)destory;
??? static void destory(private *p)
??? {
?? ??? ?free(p);
??? }
??? ?
??? public* create_public(void)
??? {
?? ??? ?private *user;
?? ??? ?user = malloc(sizeof(*(user)));
?? ??? ?user->p.print = _print_value;
?? ??? ?user->p.destory = _destory;
?? ??? ?user->private_v1 = 5;
?? ??? ?return &user->p;
??? }
H文件,print_module.h
??? typedef struct public public;
??? struct public {
?? ??? ?void (*print) (public *this);
?? ??? ?void (*destory) (public *this);
??? };
??? /**
???? * create a public instance.
???? * */
??? public* create_public(void);
main.c文件
??? #include <stdio.h>
??? #include <stdlib.h>
??? #include "print_module.h"
??? ?
??? ?
??? int main(void)
??? {
?? ??? ?public *user;
?? ??? ?user = create_public();
?? ??? ?user->print(user);
?? ??? ?user->destory(user);
??? ?
??? }
進(jìn)行簡(jiǎn)單的編譯并且執(zhí)行
??? gcc -c print_module.c
??? gcc main.c print_module.o -o main
??? ./main
??? 5
從main函數(shù)開(kāi)始講起,這種框架的思想是想要調(diào)用模塊,有如下幾個(gè)步驟:
1.包含模塊頭文件;
2.調(diào)用create相關(guān)函數(shù)創(chuàng)建相應(yīng)的模塊的結(jié)構(gòu)體;
3.利用這個(gè)結(jié)構(gòu)體作為橋梁,訪問(wèn)公有的方法。
可能看到這里,這種思想已經(jīng)理解了,每個(gè)C文件都會(huì)創(chuàng)建自己的私有結(jié)構(gòu)體,C文件每個(gè)函數(shù)的輸入?yún)?shù)都有一個(gè)私有結(jié)構(gòu)體指針,這樣函數(shù)就可以調(diào)用私有結(jié)構(gòu)體的方法和變量,同時(shí)以一種巧妙形式把這個(gè)函數(shù)原型變形成輸入?yún)?shù)既能用公有結(jié)構(gòu)體也能用私有結(jié)構(gòu)體,最終把函數(shù)指針賦值給公有結(jié)構(gòu)體的成員,讓公有結(jié)構(gòu)體可以調(diào)用。
最后稍微講講public* create_public(void)這個(gè)函數(shù)作用,它通過(guò)先創(chuàng)建一個(gè)私有結(jié)構(gòu)體,最終返回私有結(jié)構(gòu)體的一部分----即公有結(jié)構(gòu)體(因?yàn)楣薪Y(jié)構(gòu)體在私有結(jié)構(gòu)體里,私有結(jié)構(gòu)體比較大)。在這期間,給公有結(jié)構(gòu)體的方法賦值,如上面看到METHOD這個(gè)宏那么復(fù)雜,其實(shí)是為了這個(gè)create函數(shù),宏的第一句給出函數(shù)原型(也理解為定義了一個(gè)函數(shù)指針),第二句話給出了一個(gè)跟第一句話名字一樣的但是加了一個(gè)下劃線的函數(shù)指針,這個(gè)指針最終賦給公有結(jié)構(gòu)體中相應(yīng)的函數(shù)指針,為了讓公有結(jié)構(gòu)體能訪問(wèn)這個(gè)函數(shù),還有就是給私有結(jié)構(gòu)體賦自己變量和方法。
按照這種的框架思想,其他模塊想要調(diào)用這個(gè)模塊,就必須按照上述步驟,所得到的公有結(jié)構(gòu)體自然訪問(wèn)不到私有變量和方法。
---------------------
作者:喝醉的魚(yú)
來(lái)源:CSDN
原文:https://blog.csdn.net/u012895183/article/details/81544227
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)附上博文鏈接!
總結(jié)
以上是生活随笔為你收集整理的利用c语言结构体和union实现类似c++的public,private的实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 找两部电影,时间有些久了,印象模糊了。第
- 下一篇: 按摩、足疗店等,按摩一次多少钱?,足疗一