c++pointersshared-ptrsmart-pointersphysx

C++ Nvidia PhysX cannot convert PxFoundation to shared_ptr<>


Im trying to create a PxFoundation and save it in my member variable "foundation" which is a std::shared_ptr. However upon creating the object I get this:

C2440: '<function-style-cast>': cannot convert from 'physx::PxFoundation *' to 'std::shared_ptr<physx::PxFoundation>'

How can I put the raw pointer from the PxCreateFoundation function into a shared_ptr? as I'm not calling the ctor of any PhysX class I cannot use std::make_shared, so using the normal std::shared_ptr<>() constructor seems my only option?

Code:

#include <memory>
#include <PxPhysics.h>
#include "PhysXErrorCallback.hpp"
#include "PhysXDefaultAllocator.hpp"
#include <foundation/PxFoundationVersion.h>

class PhysicsEngine
{
public:


    PhysicsEngine();

    std::shared_ptr<physx::PxFoundation> foundation;

    static PhysXErrorCallback gDefaultErrorCallback;
    static PhysXDefaultAllocator gDefaultAllocatorCallback;
};

PhysicsEngine::PhysicsEngine()
{
    foundation =  std::shared_ptr<physx::PxFoundation>(PxCreateFoundation(PX_FOUNDATION_VERSION, gDefaultAllocatorCallback, gDefaultErrorCallback));
}

EDIT: After chaning the

foundation = std::shared_ptr<physx::PxFoundation>(...) 

to

foundation.reset(...)

it now gives me these errors:

1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\memory(1519): error C2440: '<function-style-cast>': cannot convert from 'physx::PxFoundation *' to 'std::shared_ptr<physx::PxFoundation>'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\memory(1519): note: No constructor could take the source type, or constructor overload resolution was ambiguous
1>physicsengine.cpp(25): note: see reference to function template instantiation 'void std::shared_ptr<physx::PxFoundation>::reset<physx::PxFoundation>(_Ux *)' being compiled
1>        with
1>        [
1>            _Ux=physx::PxFoundation
1>        ]
1>physicsengine.cpp(25): note: see reference to function template instantiation 'void std::shared_ptr<physx::PxFoundation>::reset<physx::PxFoundation>(_Ux *)' being compiled
1>        with
1>        [
1>            _Ux=physx::PxFoundation
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\memory(1519): error C2228: left of '.swap' must have class/struct/union

EDIT2:

Heres the PxCreateFoundation declaration and definition:

PX_C_EXPORT PX_FOUNDATION_API physx::PxFoundation* PX_CALL_CONV
PxCreateFoundation(physx::PxU32 version, physx::PxAllocatorCallback& allocator, physx::PxErrorCallback& errorCallback);

physx::PxFoundation* PxCreateFoundation(physx::PxU32 version, physx::PxAllocatorCallback& allocator,
                                    physx::PxErrorCallback& errorCallback)
{
    return physx::shdfnd::Foundation::createInstance(version, errorCallback, allocator);
}

PxFoundation class:

/**
\brief Foundation SDK singleton class.

You need to have an instance of this class to instance the higher level SDKs.
*/
class PX_FOUNDATION_API PxFoundation
{
  public:
    virtual void release() = 0;

  protected:
    virtual ~PxFoundation()
    {
    }
};

createInstance definition:

Foundation* Foundation::createInstance(PxU32 version, PxErrorCallback& errc, PxAllocatorCallback& alloc)
{
//...
    mInstance = reinterpret_cast<Foundation*>(alloc.allocate(sizeof(Foundation), "Foundation", __FILE__, __LINE__));

    if(mInstance)
    {
        PX_PLACEMENT_NEW(mInstance, Foundation)(errc, alloc);
        return mInstance;
    }
//...
}

Solution

  • Seems like I found the error: Most destructors in PhysX SDK are not public. Therefore trying to create a smart pointer with one of these classes results in an error. Only other option beside using a raw pointer would be to create a custom deleter:

    auto foundation = std::shared_ptr<physx::PxFoundation>(PxCreateFoundation(PX_FOUNDATION_VERSION, gDefaultAllocatorCallback, gDefaultErrorCallback), [=](physx::PxFoundation* f)
    {
        f->release();
    });