C++ 将类方法作为void函数指针传递(C+;+;11)
我有一个对象,它需要与现有的C api接口来注册一个in中断(不带参数的void函数)。我可以将中断附加到函数C++ 将类方法作为void函数指针传递(C+;+;11),c++,c++11,C++,C++11,我有一个对象,它需要与现有的C api接口来注册一个in中断(不带参数的void函数)。我可以将中断附加到函数function()。但是,我希望能够将参数传递给函数,但这会更改函数签名。我认为一种解决方法是创建一个对象来存储参数(并根据需要修改它们),然后传入一个方法(或类似方法)。然而,我还没有弄明白如何做到这一点 我试着以[=](){std::cout的形式传入一个lambda,因此您希望为不同的中断注册一个相同的中断处理程序,每个中断都具有相同但独立的数据 使用静态数据的独立模板函数怎么样
function()
。但是,我希望能够将参数传递给函数,但这会更改函数签名。我认为一种解决方法是创建一个对象来存储参数(并根据需要修改它们),然后传入一个方法(或类似方法)。然而,我还没有弄明白如何做到这一点
我试着以
[=](){std::cout的形式传入一个lambda,因此您希望为不同的中断注册一个相同的中断处理程序,每个中断都具有相同但独立的数据
使用静态数据的独立模板函数怎么样
template <unsigned int IRQ>
void irqHandler()
{
static A a(IRQ);
a.doSomething();
};
void(*interruptVectorTable[12])() =
{
// ...
&irqHandler<7>,
// ...
&irqHandler<10>,
};
模板
void irqHandler()
{
静态A(IRQ);
a、 doSomething();
};
void(*可中断的[12])()=
{
// ...
&irqHandler,
// ...
&irqHandler,
};
因此,您希望为不同的中断注册一个相同的中断处理程序,每个中断都具有相同但独立的数据
使用静态数据的独立模板函数怎么样
template <unsigned int IRQ>
void irqHandler()
{
static A a(IRQ);
a.doSomething();
};
void(*interruptVectorTable[12])() =
{
// ...
&irqHandler<7>,
// ...
&irqHandler<10>,
};
模板
void irqHandler()
{
静态A(IRQ);
a、 doSomething();
};
void(*可中断的[12])()=
{
// ...
&irqHandler,
// ...
&irqHandler,
};
这是一种非常复杂的方法。它需要一些样板代码,所以我将其包装在几个宏中(糟糕)。对于C++11
来说,锁定有些有限(读取效率较低),但如果您可以访问C++14
或更高版本,则可以改进:
// ## Header Library Code
namespace static_dispatch {
inline std::mutex& mutex()
{ static std::mutex mtx; return mtx; }
inline std::lock_guard<std::mutex> lock_for_reading()
{ return std::lock_guard<std::mutex>(mutex()); }
inline std::lock_guard<std::mutex> lock_for_updates()
{ return std::lock_guard<std::mutex>(mutex()); }
inline std::vector<void*>& cbdb()
{
static std::vector<void*> vps;
return vps;
}
inline void register_cb(void(*cb)(), void* user_data)
{
auto lock = lock_for_updates();
cbdb().push_back(user_data);
cb(); // assign id under lock
}
inline void* retreive_cb(std::size_t id)
{
auto lock = lock_for_reading();
return cbdb()[id];
}
} // namespace static_dispatch
#define CALLBACK_BOILERPLATE(id) \
static auto id = std::size_t(-1); \
if(id == std::size_t(-1)) { id = static_dispatch::cbdb().size() - 1; return; }
#define CALLBACK_RETREIVE_DATA(id, T) \
reinterpret_cast<T*>(static_dispatch::retreive_cb(id))
// ## Application Code
class A
{
public:
void member_callback_1() const
{
std::cout << s << '\n';
}
private:
std::string s = "hello";
};
void callback_1()
{
CALLBACK_BOILERPLATE(id);
auto a = CALLBACK_RETREIVE_DATA(id, A);
a->member_callback_1();
}
// The framework that you need to register your
// callbacks with
void framework_register(void(*cb)()) { cb(); }
int main()
{
A a;
// register callback with data structure
static_dispatch::register_cb(&callback_1, &a);
// Now register callback with framework because subsequent calls
// will invoke the real callback.
framework_register(&callback_1);
// etc...
}
这是一种复杂的方法。它需要一些样板代码,所以我将其包装在两个宏中(糟糕)。对于C++11
来说,锁定有些有限(读取效率较低),但如果您可以访问C++14
或更高版本,则可以改进:
// ## Header Library Code
namespace static_dispatch {
inline std::mutex& mutex()
{ static std::mutex mtx; return mtx; }
inline std::lock_guard<std::mutex> lock_for_reading()
{ return std::lock_guard<std::mutex>(mutex()); }
inline std::lock_guard<std::mutex> lock_for_updates()
{ return std::lock_guard<std::mutex>(mutex()); }
inline std::vector<void*>& cbdb()
{
static std::vector<void*> vps;
return vps;
}
inline void register_cb(void(*cb)(), void* user_data)
{
auto lock = lock_for_updates();
cbdb().push_back(user_data);
cb(); // assign id under lock
}
inline void* retreive_cb(std::size_t id)
{
auto lock = lock_for_reading();
return cbdb()[id];
}
} // namespace static_dispatch
#define CALLBACK_BOILERPLATE(id) \
static auto id = std::size_t(-1); \
if(id == std::size_t(-1)) { id = static_dispatch::cbdb().size() - 1; return; }
#define CALLBACK_RETREIVE_DATA(id, T) \
reinterpret_cast<T*>(static_dispatch::retreive_cb(id))
// ## Application Code
class A
{
public:
void member_callback_1() const
{
std::cout << s << '\n';
}
private:
std::string s = "hello";
};
void callback_1()
{
CALLBACK_BOILERPLATE(id);
auto a = CALLBACK_RETREIVE_DATA(id, A);
a->member_callback_1();
}
// The framework that you need to register your
// callbacks with
void framework_register(void(*cb)()) { cb(); }
int main()
{
A a;
// register callback with data structure
static_dispatch::register_cb(&callback_1, &a);
// Now register callback with framework because subsequent calls
// will invoke the real callback.
framework_register(&callback_1);
// etc...
}
你将无法绕过std::bind()
。模板化方法将作为静态方法工作,但实际上它与模板化自由函数相同。这就足够了吗?模板化方法中的a
无论如何都不是类成员a
。你将无法绕过std::bind()
。模板化方法可以像静态的一样工作,但实际上它与模板化的自由函数是一样的。这就足够了吗?模板化方法中的a
不是类成员a
。谢谢!这个解决方案工作得很好。我用受此启发的解决方案修改了我的问题。谢谢!这个解决方案是可行的好吧,我用我的解决方案修改了我的问题,这就是我的灵感所在。
inline std::shared_timed_mutex& mutex()
{ static std::shared_timed_mutex mtx; return mtx; }
inline std::shared_lock<std::shared_timed_mutex> lock_for_reading()
{ return std::shared_lock<std::shared_timed_mutex>(mutex()); }
inline std::unique_lock<std::shared_timed_mutex> lock_for_updates()
{ return std::unique_lock<std::shared_timed_mutex>(mutex()); }