从原理上来讲,就是一个内存地址,跳过去执行对应的代码段既然如此,在运行时决定跳到哪个地方去执行特定的代码即可,我来为大家讲解一下关于c语言指针的结构?跟着小编一起来看一看吧!
c语言指针的结构
何为函数指针?从原理上来讲,就是一个内存地址,跳过去执行对应的代码段。既然如此,在运行时决定跳到哪个地方去执行特定的代码即可。
以音频解码器作为例子:AAC 解码器,mpeg解码器,以及其他类型的解码器。那手动的多态可能会这样实现:
U32 audioHandle = AudioDecOpen(int type)
{
if(type == aac)
return aac_open();
else if(type == mpeg)
return mpeg_open();
}
这样的代码不利于扩展,没加入一个新的实例,就得改动AudioDecOpen这个函数。而且封装的不好。
另外一种方法来写:
首先定义三种公有函数的函数指针。
typedef int (*OpenFunc) (void *this);
typedef int (*CloseFunc) (void *this);
typedef int (*ControlFunc) (void *this, int command, void *param);
定义公共接口结构体 & AudioDecoder 对象:
struct module
{ OpenFunc Open; CloseFunc Close; ControlFunc Control;};
struct AudioDecoder{
struct module m;
int audioType;
void* private;
};
提供一个表驱动来方便找到对应的入口:
struct AudioPool{
int audioType;
struct module* audioModule;
}pool[] = {
{aac , aac_module},
{mpeg , mpeg_module},
};
int AudioCreate(int type , Handle *handle)
{
AudioDecoder dec = alloc_audioDec();
foreach(pool , k)
{
if(k->audioType == type)
{
dec->m = k->audioModule;
}
}
*handle = (Handle)dec;
}
这样,当外界去Create一个Audio的对象时,就已经初始化好对应的函数入口了。Open就非常简单了:
int AudioOpen(struct AudioDecoder *dec)
{
return dec->m->Open(dec);
}
其中AudioDecoder中的Private 则是在各自的Open中自己申请,自己释放,Close,Control 类似。
今后维护这个表驱动即可(pool),新的对象的支持加入进来就行了,很方便维护。
更好的维护pool
现在的pool依然拓展性不太好,毕竟每次加入新的对象都得改动pool这个表驱动。
这里提供一个更好的方法:
struct AudioPool{
int audioType;
struct module* audioModule;
}pool[MAX_POOL];
在提供一个Pool_Register(int type , struct module* module); 的功能:
int Pool_Register(int type , struct module* module);
{
for_each(pool , k)
{
if(k->type == INVALID_AUDIO_TYPE)
{
k->type = type;
k->audioModule = module;
}
}
if(k == NULL)
{
return REACH_POOL_END;
}
return NO_ERROR;
}
这样在每个实例中调用 rigister 就可以很优雅的解决这个问题。
附上两个解码器的对象的代码,Mpeg的解码器使用的是 libmad , aac的解码器使用的是 libfaad 库:
AAC代码片段:
static int Close(void *this)
{
AudioSoftDecoder *ad = (AudioSoftDecoder*)this;
if(!ad || !ad->privateData)
{
syslog(LOG_ERR , "%s(%d):Bad Parameter !!!\n" , __FUNCTION__ , __LINE__ );
return CT_ERROR_BAD_PARAMETER;
}
AacFaadPrivate *private = (AacFaadPrivate *)ad->privateData;
private->exit = TRUE;
if(private->decoderPid > 0)
{
pthread_join(private->decoderPid , NULL);
}
if(private->hDecoder)
{
NeAACDecClose(private->hDecoder);
}
free(private);
ad->privateData = NULL;
return CT_ERROR_NO_ERROR;
}
int AAC_Init()
{
return RegisterAudioSoftDec(AudioDecType_AAC ,&aacModule);
}
MPEG代码片段:
int Close(void *this)
{
AudioSoftDecoder *ad = (AudioSoftDecoder*)this;
if(!ad || !ad->privateData)
{
syslog(LOG_ERR , "%s(%d):Bad Parameter !!!\n" , __FUNCTION__ , __LINE__ );
return CT_ERROR_BAD_PARAMETER;
}
mpegMadPrivate *private = (mpegMadPrivate *)ad->privateData;
private->exit = TRUE;
if(private->decoderPid > 0)
{
pthread_join(private->decoderPid , NULL);
}
mad_decoder_finish(&private->decoder);
if(private->data.buffer)
{
free(private->data.buffer);
}
free(private);
ad->privateData = NULL;
return CT_ERROR_NO_ERROR;
}
int Control(void *this , U32 cmd ,void* param)
{
return CT_ERROR_NO_ERROR;
}
int MPEG_Init()
{
return RegisterAudioSoftDec(AudioDecType_MPEG ,&mpegModule);
}
总结使用面向对象来设计自己的代码,维护上能够减少很多工作量。在C语言里面还实现了MVC模式等,这部分也是函数指针实现的,实际上只是一个回调。但是代码维护,模块划分上,非常清晰。
,