0

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;
    }
//...
}
Kevin Kuegler
  • 75
  • 1
  • 10

2 Answers2

2

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();
});
Kevin Kuegler
  • 75
  • 1
  • 10
-1

Your foundation = line isn't actually calling a constructor. It's trying to cast the raw pointer to a shared_ptr using the syntax called a "functional cast" or "function-style cast" (#2 here), and then assign the result to the foundation variable (which has already been default-constructed). That won't work because shared_ptr has no cast from a raw pointer (to prevent it from accidentally taking ownership of things it shouldn't).

The best way to fix the problem is to use your constructor's initializer list to actually initialize foundation with the pointer:

PhysicsEngine::PhysicsEngine() :
foundation(PxCreateFoundation(PX_FOUNDATION_VERSION, gDefaultAllocatorCallback, gDefaultErrorCallback))
{
  // empty
}

This passes the pointer to foundation's constructor, as opposed to letting foundation be default-constructed and then assigning to it afterward in the constructor body. But if you really need to do it by assignment for some reason, you can use the reset function to tell foundation to take ownership of the pointer:

PhysicsEngine::PhysicsEngine()
{
    foundation.reset(PxCreateFoundation(PX_FOUNDATION_VERSION, gDefaultAllocatorCallback, gDefaultErrorCallback));
}
Wyzard
  • 33,849
  • 3
  • 67
  • 87
  • Ah good to know! I decided to take the latter approach in case I don't want to init my physics on construction. However, it gives me the errors I edited into my question. – Kevin Kuegler Feb 28 '18 at 17:47
  • "_line isn't actually calling a constructor_" -1; a cast is a way to "call the ctor" "_(user defined type T) has no cast from (type U)_" There is no such thing as a UDT having a cast from some other type – curiousguy Feb 28 '18 at 20:20
  • "_This passes the pointer to foundation's constructor_" Please provide an example (compilable code) where an argument is acceptable in a ctor init list but not in a functional cast of the same type as the member being cted – curiousguy Feb 28 '18 at 20:23