C++ Nvidia PhysX 无法将 PxFoundation 转换为 shared_ptr<>

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

我正在尝试创建一个 PxFoundation 并将其保存在我的成员变量 "foundation" 中,它是一个 std::shared_ptr。但是在创建对象时我得到了这个:

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

如何将 PxCreateFoundation 函数的原始指针放入 shared_ptr?因为我没有调用任何 PhysX 的构造函数 class 我不能使用 std::make_shared,所以使用普通的 std::shared_ptr<>() 构造函数似乎是我唯一的选择?

代码:

#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));
}

编辑: 更改

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

foundation.reset(...)

它现在给我这些错误:

1>c:\program files (x86)\microsoft visual studio17\community\vc\tools\msvc.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 studio17\community\vc\tools\msvc.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 studio17\community\vc\tools\msvc.12.25827\include\memory(1519): error C2228: left of '.swap' must have class/struct/union

EDIT2:

这里是 PxCreateFoundation 声明和定义:

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 定义:

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;
    }
//...
}

您的 foundation = 行实际上并未调用构造函数。它试图使用称为 "functional cast" 或 "function-style cast" (#2 here) 的语法将原始指针转换为 shared_ptr,然后将结果分配给 foundation 变量(已经是 default-constructed)。那是行不通的,因为 shared_ptr 没有从原始指针进行转换(以防止它意外获得它不应该拥有的东西的所有权)。

解决此问题的最佳方法是使用构造函数的初始化列表实际初始化 foundation 指针:

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

这将指针传递给 foundation 的构造函数,而不是让 foundation 成为 default-constructed 然后在构造函数主体中分配给它。但是如果由于某种原因你真的需要通过赋值来完成,你可以使用 reset 函数来告诉 foundation 获得指针的所有权:

PhysicsEngine::PhysicsEngine()
{
    foundation.reset(PxCreateFoundation(PX_FOUNDATION_VERSION, gDefaultAllocatorCallback, gDefaultErrorCallback));
}

我好像发现了错误: PhysX SDK 中的大多数析构函数不是 public。因此,尝试使用其中之一 类 创建智能指针会导致错误。 除了使用原始指针之外,唯一的其他选择是创建自定义删除器:

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