【问题标题】:How can I save a object, so that it won't get collected by the GC in C++/CX如何保存对象,使其不会被 C++/CX 中的 GC 收集
【发布时间】:2014-12-10 17:02:24
【问题描述】:

这是我的构造函数代码:

LmiVideoCapturer* LmiVideoCapturerConstruct_(LmiVideoCapturer* x, const void* implementation)
{
std::vector<LmiVideoCapturerInfo> &deviceList = LmiVideoCapturerDeviceList::Instance();
LmiVideoCapturerInfo &capturerInfo = LmiVideoCapturerInfo();
for (std::vector<LmiVideoCapturerInfo>::iterator it = deviceList.begin(); it != deviceList.end(); it++){
    if (LmiStringCompare(&it->uniqueId, &x->uniqueId) == 0){
        capturerInfo = *it;
        break;
    }
}

if (capturerInfo.uniqueId.size > 0){
    x->isBuiltin = LMI_TRUE;

    // set basic device info 
    LmiStringAssign(&x->name, &capturerInfo.name);
    LmiStringAssign(&x->model, &capturerInfo.model);
    LmiStringAssign(&x->manufacturer, &capturerInfo.manufacturer);
    x->position = capturerInfo.position;

    // set video capabilities
    LmiAllocator *a = LmiMallocAllocatorGetDefault();
    Platform::String ^deviceId = LmiStringWinRTString(&capturerInfo.uniqueId, a);
    XTRACE(L"=========================Will call from LMIVideoCapturerConstruct\n");
    LmiVideoCapturerWinRTImplementation ^impl = ref new LmiVideoCapturerWinRTImplementation(deviceId);
    if (impl->Initialize()){
        //TODO will need to save impl inside a pin_ptr (pinned pointer) so it will not be deconstructed by the GC
        x->implementation = reinterpret_cast<void*>(impl);
        LmiVideoCapturerCapability capability;
        LmiVideoCapturerCapabilityConstructDefault(&capability, a);
        capability.height = impl->encodingProfile->Video->Height;
        capability.width = impl->encodingProfile->Video->Width;
        LmiMediaFormat format; 
        LmiMediaFormatConstructFromNative(&format, impl->encodingProfile->Video->ProfileId);
        LmiVectorPushBack(LmiMediaFormat)(&capability.formats, &format);
        double usecs = ((double)impl->encodingProfile->Video->FrameRate->Denominator / impl->encodingProfile->Video->FrameRate->Numerator) * LMI_USECS_PER_SEC;
        LmiTimeRange range;
        LmiTimeRangeConstruct(&range, LmiTimeUsecs(usecs), LmiTimeUsecs(usecs));
        LmiVectorPushBack(LmiTimeRange)(&capability.ranges, &range);
        LmiVectorPushBack(LmiVideoCapturerCapability)(&x->capabilities, &capability);

        return x;
    }

}

return nullptr;

}

现在我想将“impl”保存在某个地方,这就是为什么我将它保存在 X 中,我将在函数结束时返回。但是一旦这个函数结束,GC 就会调用这个对象的解构器。如何设置这个对象在被 GC 调用时避开它?

编辑:在互联网上搜索了数小时后,我注意到 c++ 有一个称为固定指针(pin_ptr)的东西,但我在上面找到的所有示例都显示了在内部保存 int 数组。是否可以将对象保存在固定指针中?

【问题讨论】:

  • 在这个 sn-p 中没有任何 .NET 或 C++/CLI 代码。语言扩展称为 C++/CX,没有使用垃圾收集器,固定指针没有意义。当您使用 reinterpret_cast 时,编译器无法看到本机代码具有对对象的引用,因此它无法发出 AddRef() 调用以确保对象保持活动状态。将对象自己存储在静态变量或寿命足够长的类的字段中是简单的解决方法。
  • 抱歉,将其编辑为 C++/CX。所以据我了解,我不需要使用固定指针?我可以将它保存在一个静态变量中,然后使用那个?顺便说一句:我需要对象的类是另一个类,所以我不在同一个类中使用它,这是一个问题吗?
  • 找到一种方法将实例作为 ^ 传递给另一个对象。为什么需要静态变量?

标签: object null garbage-collection c++-cx pin-ptr


【解决方案1】:

C++/CX 中没有垃圾回收。

您定义的 LmiVideoCapturerWinRTImplementation^ impl 变量是一种智能指针类型,它将自动为您管理对象的生命周期。更多关于 C++/CX 类型的信息可以在这里找到:http://blogs.msdn.com/b/vcblog/archive/2012/09/17/cxxcxpart02typesthatwearhats.aspx

【讨论】:

  • 谢谢,我做了一个 Wrapper,这是一个原生结构,将智能指针保存在其中,因此不会自动管理
  • 根据定义,智能指针与 RAII 配合得很好,所以这应该不是问题。 (仅当您以某种方式破坏内存管理时。)为什么在本机结构中没有 ^ ?在 C++/CX 中很好。或者,使用 Microsoft::WRL::ComPtr。或者,在紧要关头,您可以转换为原始 IInspectable* 并自己管理 AddRef/Release 对。
【解决方案2】:

改为返回 T^,或者如果您需要将 T^ 包装在结构 U 中,只需按值返回该 U。

尽可能避免使用原始指针。也不要通过强制转换为 void* 来丢失类型信息。对于 WinRT 对象,您最多可以安全地转换为 Platform::Object^ 或 IInspectable*。在后一种情况下,使用 ComPtr 来存储拥有引用。

【讨论】:

  • pin_ptr 是 C++/CLI,此处不适用。答案帖子提到没有GC。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 2012-01-31
  • 1970-01-01
  • 2012-11-10
  • 1970-01-01
相关资源
最近更新 更多