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

Getting raw pointer from shared_ptr to pass it to function that requires raw

本文关键字:函数 raw ptr shared 获取 原始 指针      更新时间:2023-10-16

好的,首先我对C++很陌生,所以如果我的理解很差,请道歉。我会尽力解释自己。我所拥有的是我正在使用一个返回std::shared_ptr<SomeObject>的库函数,然后我有一个不同的库函数,它接受一个原始指针参数(更具体地说是 node-addon-apiNapi::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:Object时将Napi::Value的子类型传递给构造函数New函数,并且我需要在外部包装的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++ 的新手,但这似乎有点味道。但是,我通过一些调试对其进行了测试,并且可以看到引用计数上升,所以我认为我是清楚的???

这里是文档的重要部分:

Napi::

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

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

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

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

static Napi::External Napi::External::New(napi_env env,
T* data,
Finalizer finalizeCallback);

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