【发布时间】:2020-04-10 22:36:49
【问题描述】:
我正在寻找如何将类成员转换为 C 风格的回调。
最近我发现了一个特殊的 bind hack 的答案,允许将类成员绑定到 C 风格的回调:
https://stackoverflow.com/a/39524069/5405443
我有这个工作代码将函数 MyClass::f 绑定到 C 函数 f: 但我想避免将 cb_type 作为模板参数显式传递给 c_bind 函数。 在提供的示例中,CB 具有类型 void (*)(int) 并且 Func 模板参数具有 void (MyClass::*)( int) 类型。
template<typename CB, typename Func, typename... Params>
CB* c_bind(std::_Bind<Func(Params...)> function) {
return Callback<typename ActualType<CB>::type, __COUNTER__, Func>::getCallback(function);
}
typedef void (cb_type)(int);
class MyClass {
public:
void f(int x) {
std::cout << "Hello from MyClass::f(int), value: " << x << std::endl;
}
};
int main() {
MyClass mc;
auto f = c_bind<cb_type>(std::bind(&MyClass::f, mc, std::placeholders::_1));
// ^ how to avoid explicit callback type declaration here?
f(10);
return 0;
}
我还发现了这段代码 (https://gist.github.com/vikchopde/73b62314379f733e8938f11b246df49c) 用于“展开”某种功能。
bool ok = fu::is_unwrappable<decltype(&MyClass::f)>::value; // always false
// fu::unwrap_function<decltype(&MyClass::f)>::type::function_ptr blah; // won't compile
但我不知道为什么它不会起作用。
我的问题是有什么解决方法可以从具有类成员指针的类型中提取返回类型和参数列表,例如 void (MyClass::*)(int) 并构造类 C 类型 无效 (*)(int) ?
感谢您的帮助!
【问题讨论】:
-
你不会通过随机的谷歌搜索和阅读 Github 上的随机代码来解决这个问题。您需要从根本上彻底了解为什么不能这样投射,
std::bind做了什么,以及在这种情况下它是如何工作的。您需要了解所涉及的基本原理,应该是fully explained in every good C++ book。您可能不想听到有人告诉您“去读一本书并学习这个”,但这是您必须做的,才能正确地做到这一点。 -
我曾经知道如何做到这一点,我将不得不挖掘代码。它涉及在结构中编写一些机器代码,将指针添加到对象。调用 PrestoChangoSelector。然后将结构类型转换为 C 函数。想法是调用 C 函数,将对象与参数一起压入堆栈,然后调用 C++ 函数(通过跳转指令)。
-
抱歉,我以为是 Reddit 的 DarkMode!
-
std::_Bind是标准库实现的实现细节。您不应该在代码中使用它。而是像链接代码一样使用 lambda 和std::function。