Reputation: 512
I want to pass c++ objcet member callback func to an "c" lib, which just have void*. Then I use std::function to register the callback handler. But there is a problem when I cast std::function<>* to void*, seems the std::function<>* is destroyed when cast to void*.
Below is the test code.
#include <iostream>
#include <functional>
class TfLight {
public:
void print(int a) {
std::cout << "TfLight::print " << a << std::endl;
}
};
class Server {
public:
void run(int a) {
std::function<void(int)>* func = reinterpret_cast<std::function<void(int)>*>(ptr);
std::cout << func << std::endl;
(*func)(a);
}
void register(std::function<void(int)> tf) {
std::cout << (&tf) << std::endl;
// f = tf;
setPtr(&tf);
}
void setPtr(void* p) {
ptr = p;
}
std::function<void(int)> f;
void* ptr;
};
int main()
{
TfLight* tf = new TfLight();
Server* server = new Server();
server->register(std::bind(&TfLight::print, tf, std::placeholders::_1));
server->run(3333);
delete server;
delete tf;
}
When I use a global variable to holder "std::function<void(int)>", it can be called normally. How can I deal with this problem?
But there is a problem when I cast std::function<>* to void*, seems the std::function<>* is destroyed when cast to void*
Upvotes: 0
Views: 198
Reputation: 179799
std::bind
is a function. It's not on the stack or the heap.
Its return value is a temporary object, and has the usual lifetime of temporaries. That's not the problem here; the bind
return value is stored in the std::function
passed to register
.
In register
, again the normal C++ rules are followed. std::function<void(int)> tf)
is a function argument, so &tf
remains valid for the duration of the call. As soon as register
returns, tf
ceases to exist. The commented-out code is correct; you should have copied it to Server::f
.
Since you have Server::f
, the void* Server::ptr
seems entirely pointless. Yes, you can set ptr
to &f
, but why?
Upvotes: 8