2011-10-25 34 views
2

我需要一个成员函数传递到第三方外部方法:使用类成员函数作为回调?

box_self_intersection_d(mycallback); 

box_self_intersection_d是第三方外部静态方法,我不能修改它。 mycallback是我想把它传递到box_self_intersection_d的方法,它是一类功能,并访问一些成员在这个类(有和完全控制了这个类的mycallback

反正我有可以使用类的成员函数作为回调没有声明他们作为静态函数?

编辑:mycallback的签名是(const box &boxA, const box &boxB),其中box是来自第三方提供商的特殊类别。

而且signature forbox_self_intersection_d

void box_self_intersection_d(RandomAccessIterator begin,RandomAccessIterator end,Callback callback) 
+0

这种方法甚至有意义吗?请记住,非静态成员函数在类* instance *的公司中才有意义。所以你需要以某种方式将成员函数*和*实例传递给回调函数,但是哪个实例? –

+0

如果方法是固定的并且不能改变,那么在问题中有一点信息是该方法的签名是什么,因为这决定了问题的约束。 –

+0

有没有解决这个问题的方法?我面对完全相同的问题,但尽管一些答案被增加了投票数,但没有一个被标记为可接受的解决方案。 –

回答

0

有几个可能的解决方法。你可以看看这里:http://www.newty.de/fpt/callback.html#member

总之,你可以:

  • ,声明静态的“包装法”,并把类给它的实例,
  • 或者存储指针作为全局变量的对象。

希望帮助,

+0

我认为这两种解决方案都不适用于我的情况。对于1,它需要我修改'mycallback'方法签名,这是不可能的。对于2,好吧...让我们只是说我讨厌全局变量,因为潜在的线程问题。 – Graviton

1

如果回调接受用户定义的数据一个void *,你可以使用注塑void *的参数类的类型,并调用你的成员函数中的静态包装函数。

例子:

static void Foo::callback_method(void* data) { 
    static_cast<Foo*>(data)->mycallback(); 
} 

void Foo::register_my_callback() { 
    box_self_intersection_d(&Foo::callback_method, this); 
} 

大多数理智的回调库允许你通过这个void *的参数的功能,以此来拥有它的用户定义的数据。如果没有,你需要求助于肮脏的方法:

static Foo* Foo::callback_object; 
static void Foo::callback_method() { 
    callback_object->mycallback(); 
} 

void Foo::register_my_callback() { 
    callback_object = this; 
    box_self_intersection_d(&Foo::callback_method); 
} 

一般来说,如果你需要传递一个功能,就是没有别的办法:要么你有一个数据侧通道,如无效*,你的库提供者似乎已经省略了(显然是库中的一个bug),或者你需要通过全局变量传输这个指针。

+0

你能更明确吗?请记住,调用回调的方法不在我的控制之下 – Graviton

1

如果函数box_self_intersection_d需要的功能作为参数,并mycallback是一类MyClass的方法,可以使用boost::bind

box_self_intersection_d(boost::bind(&MyClass::mycallback, myClassInstance)); 

其中myClassInstance是类MyClass的实例。

+0

出于好奇,这只适用于'静态T MyClass :: mycallback(MyClass * self)'(实现为'return self-> mycallback() ')还是只使用更常见的'T MyClass :: mycallback()'?我不熟悉boost,所以我想知道是否需要额外的包装器(从我可以在线上查看的文档中看到)。 – bitmask

+0

@bitmask:我不确定这个问题,但是如果你只提到'boost :: bind',是的,它会工作来绑定一个非静态成员函数,它没有参数和/或静态成员函数一个指向'MyClass'的指针的单个参数。我担心这不是真正的问题答案,因为'box_self_intersection_d'的签名似乎不能改变,我怀疑它是否需要一个函数。 –

+0

@bitmask是的:'boost :: bind'适用于两者。特别是,非静态成员函数'无效MyClass的:: myCallBack函数()'(我认为这是原来的问题的情况下) –

0

您没有提供签名box_self_intersection_d()

一般

,如果签名是

void box_self_intersection_d(void *cb); 

甚至

void box_self_intersection_d(void (*cb)(const box&, const box&)); 

,那么你可以将指针不能把它传递给一个成员函数。

原因是sizeof(a_member_function)不同于 sizeof(a_function_pointer)。如果是这种情况,我认为你不得不使用thiton的解决方案,并创建一个静态函数。

+0

\t 'box_self_intersection_d(\t RandomAccessIterator的开头的'的是box_self_intersection_d'无效签名, RandomAccessIterator的结束, 回调回拨) – Graviton

0

由于它是CGAL,回调实际上是一个模板参数。
其唯一的约束是“回调必须是BinaryFunction概念”。
也就是说,它可以是任何可以用适当的参数“调用”的东西。

这包括具有void operator() (const box&, const box&)成员函数的任何对象。
在您的班级中实现该功能并传递*this作为回调可能是最简单的解决方案。

0

有一个可怕的解决方案,我可以想象这意味着将'this'和函数代码复制/推送到调用堆栈(或者一些其他调用者分配的段可以被编写和执行),并将函数的地址给库。回调函数然后可以找到它自己的代码地址,使用偏移/指针算术来提取'this'。并调用成员函数。应该适用于多个线程。

我特此声明今年的'可怕的哈克'奖的解决方案,使开发人员感到身体不适,但如果项目经理在你的头上指着一把霰弹枪,可能仍然实际工作。

Rgds, Martin Martin

+0

是的,(在别人呻吟之前),调用者堆栈对于一个异步回调是没有用的 - 需要一个单独的R/E段,可以在回调中取消分配。连messier:(( –

相关问题