将非静态方法或 std::function<void(...)> 作为 void (*) 参数传递
Passing a non-static method or std::function<void(...)> as a void (*) argument
我正在尝试定义一个 function/method(void MyClass::myDispatcher(int, int, void *)
或 std::function<void(int, int, void *)> myDispatcher
),它将成为主机 class.
的成员
但是,我还需要通过一个外部库将这个函数传递给它作为参数:void (*dispatcher) (int, int, void *)
.
有没有办法将非静态函数转换为所需的 void (*)(int, int, void *)
类型?
我对候选人 void MyClass::myDispatcher(int, int, void *)
的第一次尝试是使用 std::bind()
来绑定 MyClass::myDispatcher
和 this
。尽管我无法将 std::bind
的 return 类型转换为匹配 void (*)
.
第二次尝试是使用 std::function<void(int, int, void *)> myDispatcher
完成的,为此我尝试使用 reinterpret_cast<void (*)(int, int, void *)>(&myDispatcher)
来适应请求的参数。它确实编译了,但我最终在外部库中遇到了段错误。
我可以用这个例子总结我的两次尝试:
class MyClass{
MyClass() = default;
void myDispatcher(int, int, void *){
// do something
}
void init(){
myFct = [this](int, int, void*){
// do something
};
external_function(reinterpret_cast<void (*)(int, int, void *)>(&myFct));
// or the non-compiling
// external_function(std::bind(&MyClass::myDispatcher, this));
}
private:
std::function<void(int, int, void*)> myFct;
};
编辑:
正如你们中的一些人所指出的:这个 C 风格 external_function
有一个额外的 void *
参数,它作为最后一个参数传递给提供的函数!
总而言之:没有办法做这样的事情,因为函数指针和非静态成员函数之间存在根本区别。但是,C 风格的库通常会提供一种变通方法,即对提供的静态函数执行回调:
void external_function(void (*dispatcher) (int, int, void *), void* info){
// a bunch of instructions (meaningless for this example)
int a,b;
dispatcher(a,b,info);
}
一旦我们知道这一点,就可以将 info
指针转换回我们想要的 class。
不,您不能从 non-static 成员函数中获取 void (*)(int, int, void *)
。 Non-static 成员函数与自由函数有根本的不同:您需要一个对象来调用该方法。
但是,在您的代码中,您已经在使用 std::function
并且 std::function
具有将 void (Foo::*)(int, int,void*)
转换为 std::function<void(Foo*,int,int,void*)>
的构造函数。
外部库需要一个 C 风格的函数指针。我不会不接受 C++ 可调用对象(例如 std::function 或 std::bind)。您必须将 C++ 可调用对象包装在具有所需签名的普通函数中。像这样:
void dispatcher(int theInt1, int theInt2, void *theData) {
theInstanceOfMyClass.myDispatcher(theInt1, theInt2, data);
}
您可能希望将 C++ 实例的地址作为第三个参数传递,例如:
void dispatcher(int theInt1, int theInt2, void *theData) {
static_cast<MyClass *>(theData)->myDispatcher(theInt1, theInt2, data);
}
Is there a way I can convert a non-static function to the required void (*)(int, int, void *) type ?
不,没有。函数指针不能指向 non-static 成员函数,也不能指向函数包装对象。
您可以做的是指向一个普通函数,该函数又调用成员函数。挑战在于将实例放入该函数中。大多数 C 回调 API 允许将用户定义的数据以指向 void 的指针的形式传递到回调中,在这种情况下这不是问题。如果没有这样的选项,那么你只能使用全局可访问的实例,或者在回调中创建的实例。
您需要阅读 API 的文档以了解是否可以以及如何传递用户数据。回调中有一个void*
参数,提示可能就是你需要的
如上所述,这是不可能的,因为无法从(非静态)方法、闭包或 std::function
对象有意义地构造普通函数指针。
粗略地说,上面的每个构造在逻辑上都由两部分组成:一些固定代码(指向固定的静态已知函数的指针)和可变数据(手头的对象,或闭包的捕获) ).我们不能简单地扔掉第二部分。
也就是说,我建议检查库是否会调用 dispatcher
并为其 void *
参数传递一个 user-defined 指针。看到 C 风格的库函数有点常见
void register_callback(void (*dispatcher)(int,int,void *), void *user_data);
这是一个允许在 C 中模拟闭包的技巧,分别传递闭包的两个“部分”。
如果是这样,而不是
// not working, just for example
std::function<void(int, int)> f;
register_callback(f);
你可以写
// Make sure f will live long enough.
// I'm using new to stress the point, but you can use anything
// else provided that the pointer will be valid when f is
// called.
std::function<void(int, int)> *pf = new ...;
register_callback(call_the_function, pf);
前提是你已经定义了
// fixed function, independent from the std::function object
void call_the_function(int x, int y, void *p) {
std::function<void(int,int)> *pf =
(std::function<void(int,int)>*) p;
(*pf)(x,y);
}
如果您使用 new
使指针保持足够长的有效时间,请记住在不再需要回调时 delete
它。
我正在尝试定义一个 function/method(void MyClass::myDispatcher(int, int, void *)
或 std::function<void(int, int, void *)> myDispatcher
),它将成为主机 class.
但是,我还需要通过一个外部库将这个函数传递给它作为参数:void (*dispatcher) (int, int, void *)
.
有没有办法将非静态函数转换为所需的 void (*)(int, int, void *)
类型?
我对候选人 void MyClass::myDispatcher(int, int, void *)
的第一次尝试是使用 std::bind()
来绑定 MyClass::myDispatcher
和 this
。尽管我无法将 std::bind
的 return 类型转换为匹配 void (*)
.
第二次尝试是使用 std::function<void(int, int, void *)> myDispatcher
完成的,为此我尝试使用 reinterpret_cast<void (*)(int, int, void *)>(&myDispatcher)
来适应请求的参数。它确实编译了,但我最终在外部库中遇到了段错误。
我可以用这个例子总结我的两次尝试:
class MyClass{
MyClass() = default;
void myDispatcher(int, int, void *){
// do something
}
void init(){
myFct = [this](int, int, void*){
// do something
};
external_function(reinterpret_cast<void (*)(int, int, void *)>(&myFct));
// or the non-compiling
// external_function(std::bind(&MyClass::myDispatcher, this));
}
private:
std::function<void(int, int, void*)> myFct;
};
编辑:
正如你们中的一些人所指出的:这个 C 风格 external_function
有一个额外的 void *
参数,它作为最后一个参数传递给提供的函数!
总而言之:没有办法做这样的事情,因为函数指针和非静态成员函数之间存在根本区别。但是,C 风格的库通常会提供一种变通方法,即对提供的静态函数执行回调:
void external_function(void (*dispatcher) (int, int, void *), void* info){
// a bunch of instructions (meaningless for this example)
int a,b;
dispatcher(a,b,info);
}
一旦我们知道这一点,就可以将 info
指针转换回我们想要的 class。
不,您不能从 non-static 成员函数中获取 void (*)(int, int, void *)
。 Non-static 成员函数与自由函数有根本的不同:您需要一个对象来调用该方法。
但是,在您的代码中,您已经在使用 std::function
并且 std::function
具有将 void (Foo::*)(int, int,void*)
转换为 std::function<void(Foo*,int,int,void*)>
的构造函数。
外部库需要一个 C 风格的函数指针。我不会不接受 C++ 可调用对象(例如 std::function 或 std::bind)。您必须将 C++ 可调用对象包装在具有所需签名的普通函数中。像这样:
void dispatcher(int theInt1, int theInt2, void *theData) {
theInstanceOfMyClass.myDispatcher(theInt1, theInt2, data);
}
您可能希望将 C++ 实例的地址作为第三个参数传递,例如:
void dispatcher(int theInt1, int theInt2, void *theData) {
static_cast<MyClass *>(theData)->myDispatcher(theInt1, theInt2, data);
}
Is there a way I can convert a non-static function to the required void (*)(int, int, void *) type ?
不,没有。函数指针不能指向 non-static 成员函数,也不能指向函数包装对象。
您可以做的是指向一个普通函数,该函数又调用成员函数。挑战在于将实例放入该函数中。大多数 C 回调 API 允许将用户定义的数据以指向 void 的指针的形式传递到回调中,在这种情况下这不是问题。如果没有这样的选项,那么你只能使用全局可访问的实例,或者在回调中创建的实例。
您需要阅读 API 的文档以了解是否可以以及如何传递用户数据。回调中有一个void*
参数,提示可能就是你需要的
如上所述,这是不可能的,因为无法从(非静态)方法、闭包或 std::function
对象有意义地构造普通函数指针。
粗略地说,上面的每个构造在逻辑上都由两部分组成:一些固定代码(指向固定的静态已知函数的指针)和可变数据(手头的对象,或闭包的捕获) ).我们不能简单地扔掉第二部分。
也就是说,我建议检查库是否会调用 dispatcher
并为其 void *
参数传递一个 user-defined 指针。看到 C 风格的库函数有点常见
void register_callback(void (*dispatcher)(int,int,void *), void *user_data);
这是一个允许在 C 中模拟闭包的技巧,分别传递闭包的两个“部分”。
如果是这样,而不是
// not working, just for example
std::function<void(int, int)> f;
register_callback(f);
你可以写
// Make sure f will live long enough.
// I'm using new to stress the point, but you can use anything
// else provided that the pointer will be valid when f is
// called.
std::function<void(int, int)> *pf = new ...;
register_callback(call_the_function, pf);
前提是你已经定义了
// fixed function, independent from the std::function object
void call_the_function(int x, int y, void *p) {
std::function<void(int,int)> *pf =
(std::function<void(int,int)>*) p;
(*pf)(x,y);
}
如果您使用 new
使指针保持足够长的有效时间,请记住在不再需要回调时 delete
它。