从shared_ptr获取原始指针,以将其传递给需要原始指针的函数

Nic*_*and 5 c++ memory-management smart-pointers shared-ptr node-addon-api

好吧,首先我对C ++还是很陌生,所以如果我的理解很差,我深表歉意。我会尽力解释自己。我所拥有的是我正在使用一个返回a的库函数,std::shared_ptr<SomeObject>然后我有一个采用原始指针参数的库函数(更具体地说是node-addon-api Napi::External<T>::New(Napi::Env env, T *data)静态函数)。我想Napi::External使用我的std :: shared_ptr 创建一个对象。我目前正在做的是这样的:

{
    // ...
    std::shared_ptr<SomeObject> pSomeObject = something.CreateSomeObject();
    auto ext = Napi::External<SomeObject>::New(info.Env(), pSomeObject.get());
    auto instance = MyNapiObjectWrapper::Create({ ext });
    return instance;
}
Run Code Online (Sandbox Code Playgroud)

但是我担心这会遇到内存问题。我的pSomeObject仅存在于当前作用域中,因此我想应该在返回之后发生,它的引用计数将降为0,并且它指向的SomeObject实例将被销毁,因此我返回的实例将出现问题使用此对象。但是我已经能够从我的实例运行此代码并在SomeObject上调用函数,所以我在想我的理解可能是错误的。

我的问题是当给定共享指针时该怎么办,但由于其他第三方库要求,我需要处理原始指针?向我提出的一个选择是对对象进行深层复制并创建一个指向该对象的指针。

如果我对这方面的理解是错误的,请纠正我,因为我说过我对C ++很陌生。

===========================

编辑:

因此,我从原始帖子信息中丢失了有关所有权以及该区块的确切含义。该块是用于实例的实现的实例方法Napi::ObjectWrap。此实例方法需要返回Napi::Object,供node.js中的调用者使用。我正在使用,Napi::External因为在创建I return 时需要将子类型传递Napi::Value给构造New函数Napi:Object,并且我需要在包装SomeObject中提取包装对象的外部对象,MyNapiObjectWrapper如下所示:

class MyNapiObjectWrapper
{
private:
    SomeObject* someObject;
    static Napi::FunctionReference constructor; // ignore for now
public:
    static void Init(Napi::Env env) {...}
    MyNapiObjectWrapper(const CallbackInfo& info)
    {
        Napi::Env env = info.Env();
        Napi::HandleScope scope(env);

        // My original code to match the above example
        this->someObject = info[0].As<const Napi::External<SomeObject>>().Data();
    }

    DoSomething()
    {
        this->someObject->DoSomething();
    }
}
Run Code Online (Sandbox Code Playgroud)

从那时起,我意识到我可以在创建外部对象时传递共享指针的地址,并按以下方式使用它

// modified first sample
{{
    // ...
    std::shared_ptr<SomeObject> pSomeObject = something.CreateSomeObject();
    auto ext = Napi::External<SomeObject>::New(info.Env(), &pSomeObject);
    auto instance = MyNapiObjectWrapper::Create({ ext });
    return instance;
}

// modified second sample
class MyNapiObjectWrapper
{
private:
    std::shared_ptr<SomeObject> someObject;
    static Napi::FunctionReference constructor; // ignore for now
public:
    static void Init(Napi::Env env) {...}
    MyNapiObjectWrapper(const CallbackInfo& info)
    {
        Napi::Env env = info.Env();
        Napi::HandleScope scope(env);

        // My original code to match the above example
        this->someObject = 
            *info[0].As<const Napi::External<std::shared_ptr<SomeObject>>>().Data();
    }

    DoSomething()
    {
        this->someObject->DoSomething();
    }
}
Run Code Online (Sandbox Code Playgroud)

所以现在我传递一个指向shared_ptr的指针来创建我的Napi::External,我的问题现在可以了吗?就像我刚开始说的那样,我是c ++的新手,但这似乎有点难闻。但是我通过一些调试对其进行了测试,并且可以看到引用计数增加了,所以我认为我很清楚吗???

t.n*_*ese 3

这是文档的重要部分:

Napi::External 模板类实现了使用任意 C++ 数据创建 Napi::Value 对象的功能。用户有责任管理任意 C++ 数据的内存

所以需要确保传递给的对象存在,data直到Napi::External Napi::External::NewNapi::External<T>对象被销毁。

所以您显示的代码不正确。

您可以做的是将Finalize回调传递给该New函数:

static Napi::External Napi::External::New(napi_env env,
                    T* data,
                    Finalizer finalizeCallback);
Run Code Online (Sandbox Code Playgroud)

并使用 lambda 函数作为Finalize,该 lambda 可以通过捕获到共享指针来保存一个副本,从而允许在调用 Finalize 之前保持共享指针处于活动状态。

std::shared_ptr<SomeObject> pSomeObject = something.CreateSomeObject();
auto ext = Napi::External<SomeObject>::New(
                  info.Env(), 
                  pSomeObject.get(),
                  [pSomeObject](Env /*env*/, SomeObject* data) {});
Run Code Online (Sandbox Code Playgroud)