将C++实例方法与C回调函数混合使用
Mixing C++ instance methods with C callback functions
问题
我有来自一个名为Foo
:的C库的以下C回调签名
void (* RequestCallbackFunc)(int)
这个库还提供了一个用于注册所述回调的实用函数。
extern void SetRequestCallback(RequestallbackFunc request_cbf);
我有一个带有实例方法HandleRequest
的C++类App
。当调用request_cbf
时,调用HandleRequest
的正确方法是什么?
我天真的解决方案
App.hpp
#include <Foo.h> // include my C library
#include <Bar.hpp>
class App {
public:
App();
~App();
void HandleRequest(int x);
public:
Bar * bar_; // raw pointer for demonstration purposes
}
应用.cpp
#include "App.hpp"
extern "C" {
static void handle_request(int x);
}
static void handle_request(int x) {
static std::auto_ptr<App> my_app( new App() );
my_app->HandleRequest(x);
}
App::App() {
SetRequestCallback( handle_request );
bar_ = new Bar();
}
App::~App() {
delete bar_;
}
void App::HandleRequest(int x) {
bar_->DoSomething( x );
// more 'work'...
}
我处理这个问题的方法正确吗?有没有其他方法可以将C++与C回调接口?
回调中int
参数的用途是什么?
设计良好的C接口API通常提供一种将"status"参数传递给C函数回调的方法(可以用于传递一些信息,如C++类实例this
指针),如CreateThread的LPVOID lpParameter
。
为什么要使用指针?
static void handle_request(int x) {
static A instance;
instance.HandleRequest(x);
}
(Bar
也是如此),但老实说,你也可以直接调用Bar
中的方法(除非需要通过A
重定向)
或者,不是一个自由函数,而是传递一个指向A
中匹配相同签名的静态函数的指针-在这个指针中,您可以访问A
的单个实例来使用。。。
顺便说一句。一些api使用一种模式,在注册期间,您可以传入指向某些用户数据的指针,这些数据在回调中传递,例如,这可以是指向A
实例的指针来处理回调-这样您就可以避免所有的单例业务。。。
我会创建另一个类,它可以静态访问,并注册不同的对象来管理回调。要使用的对象可以由x参数确定(或者,如果没有必要,可以注册一个处理程序)。
// Pseudocode
class Middleman {
// map to select the handler object
std::map<int, App> handlersMap_;
public:
registerNewHandler(int x, const App& a) {
// add new entry to the map
[...]
}
static std::map<int, App> getHandlersMap() {
return handlersMap_;
}
}
管理回调:
static void handle_request(int x) {
Middleman::getHandlersMap[x].HandleRequest(x);
}
有了这种设计,你就有了极大的灵活性。Middleman的映射可以由一个单独的处理程序代替,该处理程序使用相同的registerNewHandler方法进行注册。
尝试使用cify技巧并尝试向C提供lambda对象,不过,您需要小心:
https://codereview.stackexchange.com/questions/79612/c-ifying-a-capturing-lambda
static void handle_request(int x) {
static std::auto_ptr<App> A( new A() );
A->HandleRequest(x);
}
这是一种单例。既然这是一个反模式,所以它是坏的。
我会创建一个函数,以及一个全局变量或类型App。类似这样的东西:
//App.hpp
#include <Foo.h> // include my C library
#include <Bar.hpp>
class App {
public:
App();
~App();
void HandleRequest(int x);
public:
Bar * bar_; // raw pointer for demonstration purposes
}
extern App app;
void HandlerRequest(int x);
然后实现:
//App.cpp
#include "App.hpp"
App::App() : bar(new Bar) {
SetRequestCallback( handle_request );
}
App::~App() {
delete bar_;
}
void App::HandleRequest(int x) {
bar_->DoSomething( x );
// more 'work'...
}
App app;
void HandlerRequest(int x)
{
app.HandlerRequest(x);
}
- 使用英特尔内部函数 (AVX) 中的混合说明
- 将 lambda 函数转换为具有混合 lambda 引入器和参数列表的函子结构
- 好奇的混合与可变参数构造函数
- 参数的混合值,当我调用指针成员函数时
- 混合内联和宏函数
- 混合 C 和 C++.. 对函数的未定义引用
- 混合 c++ 和汇编不能将多个参数从C++函数传递到程序集
- 混合类和函数模板
- 混合模板类型的模板参数包(std::使用可选参数重新创建函数)
- 函数模板与重载混合
- 重载+运算符问题与其他类中的友元函数混合
- 混合函数-增加浮点出现次数
- 什么是可以与C++混合的好的函数式语言
- 将从基类继承的构造函数与自定义构造函数混合使用
- 在构造函数中混合可变参数模板和初始值设定项列表
- 是否可以混合使用虚拟函数和函数对象以使用标准算法
- 在Matlab中使用OS X编译/混合imrender函数时出错
- 将构造函数与固定参数混合,将构造函数与构造函数模板混合在一起
- 将C++实例方法与C回调函数混合使用
- 与C函数混合时出现C++unique_ptr错误