Reputation: 83264
I would need a member function to be passed into a third party external method:
box_self_intersection_d(mycallback);
The box_self_intersection_d
is a third party external static method, and I cannot modify it. mycallback
is a method I want to pass it into the box_self_intersection_d
, it is a class function and is accessing some members in this class ( have full control for this class and the mycallback
)
Is there anyway I can use class member functions as callbacks without declaring them as static functions?
Edit: the signature of mycallback
is (const box &boxA, const box &boxB)
, where box
is a special class from the third party provider.
And the signature for box_self_intersection_d
is
void box_self_intersection_d(RandomAccessIterator begin,RandomAccessIterator end,Callback callback)
Upvotes: 3
Views: 578
Reputation: 24867
There is a horrible solution that I can conceive of that means copying/pushing 'this' and function code to the calling stack, (or some other caller-allocated segment that can be made writeable and executable), and passing the address of the function to the library. The called-back function could then find its own code address, extract 'this' using an offset/pointer arith. and call a member function. Should work for multiple threads.
I hereby claim this years 'Gruesome Hack' award for a solution that makes developers feel physically ill but might still actually work if a project manager is pointing a shotgun at your head.
Rgds, Martin
Upvotes: 0
Reputation: 66431
Since it's CGAL, the callback is actually a template parameter.
Its only constraints are "Callback must be of the BinaryFunction concept".
That is, it can be anything that is "callable" with the proper parameters.
This includes any object with a void operator() (const box&, const box&)
member function.
Implementing that function in your class and passing *this
for the callback would probably be the simplest solution.
Upvotes: 0
Reputation: 2426
You haven't provided the signature box_self_intersection_d()
in general, if the signature is
void box_self_intersection_d( void *cb );
or even
void box_self_intersection_d( void (*cb)(const box&, const box&) );
then you cannot pass it a pointer to a member function.
The reason is that sizeof(a_member_function)
is different than
sizeof(a_function_pointer)
. If this is the case, I think you are forced to use thiton's solution, and create a static function.
Upvotes: 0
Reputation: 36049
If the callback accepts a void* for user-defined data, you can use a static wrapper function that casts the void* argument to the class type and calls your member function.
Example:
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);
}
Most sane callback libraries allow you to pass this void* argument to the functions as a way to have user-defined data in it. If not, you'll need to resort to the dirty method:
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);
}
In general, if you need to pass a function, there is just no other way: Either you have a data side-channel like the void*, which your library provider seems to have omitted (and is clearly a bug in the library), or you need to transport the this pointer via a global variable.
Upvotes: 1
Reputation: 2552
If the function box_self_intersection_d
takes a functional as parameters, and mycallback
is a method of a class MyClass
, you can use boost::bind
:
box_self_intersection_d( boost::bind( &MyClass::mycallback, myClassInstance ) );
where myClassInstance
is the instance of the class MyClass
.
Upvotes: 2
Reputation: 2673
There are a couple of possible workarounds. You can have a look here: http://www.newty.de/fpt/callback.html#member
In short, you can either:
Hope that helps,
Upvotes: 0