10月 2020

一种通过C++模板方式识别无用户数据C回调函数的方法

今天记录一个个人觉得有点意思的问题:C++代码中调用C API时,对于C回调函数的处理问题,如何识别出调用API时的信息?

这个问题,大部分API都是通过调用时提供传递用户数据的方式实现的,如libcurl中的CURLOPT_WRITEDATA,CURLOPT_READDATA ,通过curl_easy_setopt方式将任意用户数据指针传递给CURL句柄,并在执行上传下载时的回调函数内透传给调用方,这样在例如多线程并发上传下载时就可以很方便的识别出是哪个上传下载任务的回调了。但是,如果API及回调函数内没有提供传递用户数据的接口和回调参数的话,是不是就一定无法完成识别调用上下文信息的功能呢?比如下列的C函数API:

// C-Style callback function without user context
typedef void (*c_api_callback_no_context)(int count);
// C-Style callback function with user context
typedef void (*c_api_callback_context)(int count, void * user_context);

// C API function that will trigger the callback function
void c_api_start_counting_no_context(c_api_callback_no_context callback, int max);
void c_api_start_counting_context(c_api_callback_context callback, int max, void * user_context);

c_api_start_counting_context及配套的c_api_callback_context回调为可以透传用户数据的版本,而c_api_start_counting_no_context及c_api_callback_no_context则只提供了逻辑用回调参数count,没有可用于识别context的用户数据指针,那么如何在不碰C源码的前提下(闭源C库或不想做侵入式修改)做到和带用户数据回调一样的效果呢?目前想到的一种方法是通过C++模板生成不同地址的回调函数配合上下文信息映射来实现:

Continue reading…