【发布时间】:2016-08-13 17:10:23
【问题描述】:
我想将 Linux 系统调用 API(克隆)包装到 C++ 类中。
但是,这个API需要一个函数指针,而且它的参数列表是固定的,例如:
typedef int (*callback)(void *);
void system_call(callback f) {
void *t = nullptr;
f(t);
}
现在,我的班级如下:
class Foo {
public:
void start() {
// WRONG: cannot pass non-static member function due to pointer `this`
system_call(this->foo);
}
private:
int foo(void *args) {
f->necessary();
return 0;
}
void necessary() {
std::cout << "call success!!!" << std::endl;
}
};
int main() {
Foo obj;
obj.start();
}
所以,重要的问题是:
- system_call 的参数是固定不变的。
- 方法
start()必须是非静态的。
我正在考虑这个,通过使用静态成员:
class Foo {
public:
void start() {
auto func = std::bind(foo, std::placeholders::_1, this);
system_call(func); // WRONG: cannot convert std::_Bind to a function pointer
}
private:
static int foo(void *args, Foo *f) {
f->necessary();
return 0;
}
void necessary() {
std::cout << "call success!!!" << std::endl;
}
};
或者这个,通过使用带有捕获的 lambda:
class Foo {
public:
void start() {
auto func = [this](void *args) -> int {
this->necessary();
};
system_call(func); // WRONG: cannot convert a lambda with captures to a function pointer
}
private:
void necessary() {
std::cout << "call success!!!" << std::endl;
}
};
他们都错了。
有解决这个问题的方法吗?
附:我认为这是对封装的巨大要求,但是在这里我发现一些答案并不优雅(他们修改了参数列表,无法用于系统调用):
【问题讨论】:
-
什么是“Linux 系统调用 API”?这具有 XY 问题的所有潜力。虽然有几个经典的 hack 来实现类方法回调,但我强烈怀疑是 XY 问题,并且对于这个特定的“Linux 系统调用 API”可能有更合适的答案。
-
哇,高信噪比:1 行系统调用需要 11 行。我建议您查看IOCCC 规则。
-
调用静态函数时不需要
this,所以不需要std::bind -
@ThomasMatthews 好吧,你说得对,但是我们正在尝试使用 C++,所以我们必须将它变形为一个对象。如果我们直接使用系统调用,那为什么我们只是在项目中改成C代码呢?
-
你想wrap系统调用还是warp它?或者你想对call(me)back函数进行系统调用?
标签: c++