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

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

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

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

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

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

编辑:

因此,我在最初的帖子信息中缺少有关所有权以及此区块的确切含义的信息。该块是我对Napi::ObjectWrap实例的实现的实例方法。这个实例方法需要返回一个Napi::Object,它将对node.js中的调用者可用。我正在使用Napi::External,因为在创建返回的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();
    }
}

从那时起,我意识到我可以在创建外部对象时传递共享指针的地址,并按以下方式使用它
// 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();
    }
}

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

最佳答案

这里是documentation的重要部分:



因此,您需要确保将data传递给Napi::External Napi::External::New的对象退出,直到Napi::External<T>对象被破坏为止。

因此,您显示的代码不正确。

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



并使用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) {});

10-06 14:16