将 std::function<void ()> 转换为 void (*)()
Convert std::function<void ()> to void (*)()
所以我在 C++ 中有一个成员函数,它接收一个 std::function<void>
,我想将它传递给 wiringPi 函数:
void my_class::on_change(std::function<void()> func) const
{
wiringPiISR(
wiring_pi_pin_number_,
INT_EDGE_BOTH,
func);
}
我收到错误 cannot convert ‘std::function<void()>’ to ‘void (*)()’ in initialization
。我在网上看过,我只发现有一百行指针和引用转换并且不在 pi 上编译的东西。在这里寻找任何帮助。我应该一直使用 void (*)()
吗?这似乎是错误的做法。我可以找到很多关于将 void (*)()
转换为 std::function<void>
但不是相反的方法..
PS:我是个 C++ 菜鸟。我的主要语言是 C# 和其他一些高级语言,所以仍在学习这门语言,但不确定我在这里缺少什么..
Convert std::function<void ()> to void (*)()
你不能。
Should I be using void (*)() all the way up the stack?
是的。
从技术上讲,使用 std::function 可能可行,但您必须依赖全局状态,使用 std::function 的好处可能不值得付出这笔代价。
This seems like the wrong approch.
鉴于您使用的 API 的限制,它不是。
这里有一个例子来说明如何做到这一点。
template<class Sig> using pfunc_t=Sig*;
template<class Sig>
struct callback_entry{
pfunc_t<Sig> pf = nullptr;
std::function<Sig> f;
};
trmplate<class Sig, std::size_t N>
using callback_table = std::array< callback_entry<Sig>, N >;
template<class Sig, std::size_t N, callback_table<Sig,N>* ptable, class R, class...Args, std::size_t...Is>
callback_table<Sig,N> make_table( std::index_sequence<Is...> ){
return {{
{[](Args... args)->R{ return (*ptable)[Is].f(std::forward<Args>(args)); }}...
}};
}
template<std::size_t N, class R, class...Args>
callback_table<R(Args...), N> callbacks = make_table<R(Args...), N, &callbacks<N,R,Args...>, R, Args...>(std::make_index_sequence<N>{});
template<std::size_t N, class R, class...Args>
pfunc_t<R(Args...)> register_callback( std::function<R(Args...)> f ){
for(auto&& entry:callbacks<N,R,Args...>){
if (entry.f) continue;
entry.f=std::move(f);
return entry.pf;
}
}
template<std::size_t N, class R, class...Args>
void recycle_callback( pfunc_t<R(Args...)> pf ){
for(auto&& entry:callbacks<N,R,Args...>){
if (pf!=entry.pf) continue;
entry.f=nullptr;
}
}
很多错别字,可能还有语法错误,但我希望思路清晰。
我们制作了一个全局函数指针数组和固定大小的标准函数。函数指针知道它们的索引,所以它们查找 std 函数并 运行 它。注册查找未使用的 std 函数,填充它,然后 returns 函数指针。
保持 N 低,因为它会占用可执行代码内存和 运行时间内存。但是,如果它太低,您将 运行 退出回调。
要将 std::function<void()>
转换为 void(*)()
,请使用 std::function::target<>()
函数。
目标函数returns指向存储的可调用函数目标的指针,如下面的代码所示。
void f()
{
cout << "f()" << endl;
}
void f1(void(*p)())
{
p();
}
int main() {
// Convert std::function<void()> to void(*)()
std::function<void()> fp = &f;
auto p1 = fp.target<void(*)()>();
void (*p2)() = *p1;
p2();
f1(p2);
}
输出:
f()
f()
所以我在 C++ 中有一个成员函数,它接收一个 std::function<void>
,我想将它传递给 wiringPi 函数:
void my_class::on_change(std::function<void()> func) const
{
wiringPiISR(
wiring_pi_pin_number_,
INT_EDGE_BOTH,
func);
}
我收到错误 cannot convert ‘std::function<void()>’ to ‘void (*)()’ in initialization
。我在网上看过,我只发现有一百行指针和引用转换并且不在 pi 上编译的东西。在这里寻找任何帮助。我应该一直使用 void (*)()
吗?这似乎是错误的做法。我可以找到很多关于将 void (*)()
转换为 std::function<void>
但不是相反的方法..
PS:我是个 C++ 菜鸟。我的主要语言是 C# 和其他一些高级语言,所以仍在学习这门语言,但不确定我在这里缺少什么..
Convert std::function<void ()> to void (*)()
你不能。
Should I be using void (*)() all the way up the stack?
是的。
从技术上讲,使用 std::function 可能可行,但您必须依赖全局状态,使用 std::function 的好处可能不值得付出这笔代价。
This seems like the wrong approch.
鉴于您使用的 API 的限制,它不是。
这里有一个例子来说明如何做到这一点。
template<class Sig> using pfunc_t=Sig*;
template<class Sig>
struct callback_entry{
pfunc_t<Sig> pf = nullptr;
std::function<Sig> f;
};
trmplate<class Sig, std::size_t N>
using callback_table = std::array< callback_entry<Sig>, N >;
template<class Sig, std::size_t N, callback_table<Sig,N>* ptable, class R, class...Args, std::size_t...Is>
callback_table<Sig,N> make_table( std::index_sequence<Is...> ){
return {{
{[](Args... args)->R{ return (*ptable)[Is].f(std::forward<Args>(args)); }}...
}};
}
template<std::size_t N, class R, class...Args>
callback_table<R(Args...), N> callbacks = make_table<R(Args...), N, &callbacks<N,R,Args...>, R, Args...>(std::make_index_sequence<N>{});
template<std::size_t N, class R, class...Args>
pfunc_t<R(Args...)> register_callback( std::function<R(Args...)> f ){
for(auto&& entry:callbacks<N,R,Args...>){
if (entry.f) continue;
entry.f=std::move(f);
return entry.pf;
}
}
template<std::size_t N, class R, class...Args>
void recycle_callback( pfunc_t<R(Args...)> pf ){
for(auto&& entry:callbacks<N,R,Args...>){
if (pf!=entry.pf) continue;
entry.f=nullptr;
}
}
很多错别字,可能还有语法错误,但我希望思路清晰。
我们制作了一个全局函数指针数组和固定大小的标准函数。函数指针知道它们的索引,所以它们查找 std 函数并 运行 它。注册查找未使用的 std 函数,填充它,然后 returns 函数指针。
保持 N 低,因为它会占用可执行代码内存和 运行时间内存。但是,如果它太低,您将 运行 退出回调。
要将 std::function<void()>
转换为 void(*)()
,请使用 std::function::target<>()
函数。
目标函数returns指向存储的可调用函数目标的指针,如下面的代码所示。
void f()
{
cout << "f()" << endl;
}
void f1(void(*p)())
{
p();
}
int main() {
// Convert std::function<void()> to void(*)()
std::function<void()> fp = &f;
auto p1 = fp.target<void(*)()>();
void (*p2)() = *p1;
p2();
f1(p2);
}
输出:
f()
f()