how to cast void* to shared_ptr<mytype>

10,020

Since you are storing a pointer to an instance of std::shared_ptr you need to cast the value returned by getUserPointer to std::shared_ptr<>* instead of just std::shared_ptr<>.

std::shared_ptr<disk_node>* u_poi
  = static_cast< std::shared_ptr<disk_node>* >(RayCallback.m_collisionObject->getUserPointer());
Share:
10,020
Alexandru Staetu
Author by

Alexandru Staetu

Updated on June 08, 2022

Comments

  • Alexandru Staetu
    Alexandru Staetu almost 2 years

    I have a problem with an OpenGL project, converting from a void* pointer to a shared_ptr<mytype>.

    I am using Bullet to set pointers on the rigid body with:

    root_physics->rigidBody->setUserPointer(&this->root_directory->handle);
    

    The handle is of type shared_ptr<mytype>.

    The void* pointer is returned by Bullet's library function, getUserPointer():

    RayCallback.m_collisionObject->getUserPointer()
    

    To convert back to mytype, static_cast is not working:

    std::shared_ptr<disk_node> u_poi = static_cast< std::shared_ptr<disk_node> >( RayCallback.m_collisionObject->getUserPointer() );
    

    The error, at compilation time:

    /usr/include/c++/4.8/bits/shared_ptr_base.h:739:39: error: invalid conversion from ‘void*’ to ‘mytype*’ [-fpermissive]
    

    Any idea how I can convert from the void* returned by getUserPointer() to shared_ptr<mytype>?

  • Captain Obvlious
    Captain Obvlious about 10 years
    reinterpret_cast is unnecessary here and dangerous. Since std::shared_ptr<disk_node>* can be implicitly converted to void* static_cast is more than happy to convert void* to std::shared_ptr<disk_node>*.
  • SwiftMango
    SwiftMango about 10 years
    Inappropriate use of casting here.
  • Alexandru Staetu
    Alexandru Staetu about 10 years
    While this corrected the error, accessing data from u_poi resulted in another error: error: ‘class std::shared_ptr<disk_node>’ has no member named ‘name’. To fix this, i moved the first asterisk before static_cast. std::shared_ptr<disk_node> u_poi = * static_cast< std::shared_ptr<disk_node>* >( RayCallback.m_collisionObject->getUserPointer() );
  • Captain Obvlious
    Captain Obvlious about 10 years
    You need to dereference the pointer (to std::shared_ptr) first. (*u_poi)->name should do the trick.
  • Mike Weir
    Mike Weir over 7 years
    Is this considered common practice/safe? That is, can std::shared_ptr<> be safely stored in void* user pointers provided by libraries? Planning to use this solution but wondered if this solution was more than just an answer to this specific question.
  • Captain Obvlious
    Captain Obvlious over 7 years
    @MikeWeir Yes, in situations where you need to interface with a C library or poorly thought out C++ library that use void pointers in this way it's common. It is not safe however because there are zero checks or guarantees that the pointer is what you think it is. Unless you are required to use a void pointer (i.e. interface with a C library) you should avoid this approach and instead use a polymorphic base interface.
  • Hackless
    Hackless about 3 years
    If the same void* is cast to another shared_ptr somewhere else, will the underlying object be deleted twice? I cannot see why this static_cast technique can support proper accounting for the newly minted shared pointers.