包装函数指针

前端之家收集整理的这篇文章主要介绍了包装函数指针前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图包装一个库用于移植目的.图书馆公开了一个功能说 –
fooLib(int,char,function pointer A);

函数指针A的签名是

void handler(DataFormat);

其中DataFormat是一个结构

我不希望我的包装器公开这个库的回调函数.我想创建一个应该由我的包装器的使用者使用的不同功能

int handlerNew(NewDataFormat);

其中NewDataFormat是我的结构

现在的问题是如何将这两个功能联系起来?每当库调用处理程序时,我希望它在从DataFormat填充NewDataFormat结构后调用我的回调handlerNew.

解决方法

只要您不需要线程安全,这并不难.您只需提供一个私有(静态)处理程序和库的接口,该接口将库数据结构转换为您的包装版本,然后使用它作为参数调用您的回调.您的界面将如下所示:
// wrapped_foo_lib.h
typedef struct { ... } NewDataFormat;
typedef void (*WRAPPED_CALLBACK)(NewDataFormat);
void wrappedFooLibCall(int x,char c,WRAPPED_CALLBACK cb);

您的实现,客户永远不会看到:

// wrapped_foo_lib.c
// This static var makes this module _not_ thread safe.
static WRAPPED_CALLBACK wrapped_callback;

static void private_handler(DataFormat data) {
  NewDataFormat new_data = ...; // extract new_data from data
  wrapped_callback(new_data);
}

void wrappedFooLibCall(int x,WRAPPED_CALLBACK cb) {
  wrapped_callback = cb;      
  foo_lib(x,c,private_handler);
}

非线程安全性是每个API回调应该包含您要定义的void *的原因,它将传递给回调.即您的家具图书馆应定义为

fooLib(int,void (*)(DataFormat,void *env));
void handler(DataFormat,void *env);

现在当你调用fooLib时,你提供任何结构作为env,它会传回给你.这样你可以省去包装器中的静态变量:

// wrapped_foo_lib.c
typedef struct { WRAPPED_CALLBACK wrapped_callback; } ENV;

static void private_handler(DataFormat data,void *void_env) {
  ENV *env = (ENV*)void_env;
  NewDataFormat new_data = ...; // extract new_data from data
  env->wrapped_callback(new_data);
}

void wrappedFooLibCall(int x,WRAPPED_CALLBACK cb) {
  ENV env[1] = {{ cb }};      
  foo_lib(x,env);
}

这是线程安全的,因为ENV是堆栈分配的.一个很好的例子就是libpng.

随意将C90更新为更现代的语法.

猜你在找的C&C++相关文章