I have an old C-style library that uses callback with unsigned long for user argument and I want to pass my shared_ptr to callback so that reference count is incremented.
void callback( unsigned long arg ) {
std::shared_ptr<my_class> ptr = ??? arg ???
}
void starter_function() {
std::shared_ptr<my_class> ptr = std::make_shared<my_class>();
unsigned long arg = ??? ptr ???
// pass to library so it may be used by callback
}
Currently I use get() on shared_ptr and then use C-style cast but this creates a problem when start_function goes out of scope.
Create a static store (which can be based on std::map<unsigned long, std::shared_ptr<T>>
). Provide functions to:
shared_ptr
corresponding to a particular unsigned long(The last two functions can be combined).
This has the attraction of not needing to do any dodgy casts between pointers and unsigned long, and also (if the return value is based on an incrementing counter which you test for uniqueness), makes it much easier to find problems where one object is created, deleted, and then another object created at the same address.
This is a sketch of the idea: (Note in particular, it is not thread safe!)
template typename<T>
class Store
{
static std::map<unsigned long, std::shared_ptr<T>> store;
unsigned long h;
bool contains(unsigned long i)
{
return store.find(i) != store.end();
}
public:
unsigned long save(const std::shared_ptr& ptr)
{
if (store.size() >= std::numeric_limits<unsigned long>::max())
{
// Handle error. Only possible if 64 bit program with
// 32 bit unsigned long.
}
// find an unused handle.
do
{
++h;
}
while(contains(h)); // Not a good approach if there are main long-lived objects, and h might wrap.
// Store and return handle.
store[h] = ptr;
return h;
}
std::shared_ptr<T> retrieve(unsigned long handle)
{
if (!contains(handle))
{
// handle error
}
const auto result = store[handle];
store.erase(handle);
return result;
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With