1

This is the code that I have for the constructor:

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;

}

Now I want to save "impl" somewhere, thats why I saved it in X that I will return at the end of the function. BUT as soon as this function is ended, a GC calls the deconstructor for this object. How can I set this object to be avoided by the GC, when it is called?

EDIT: After hours of searching on the internet I noticed that c++ has something called pinned pointers (pin_ptr) but all the examples I found on it, shows saving arrays of int inside. Is it possible to save a object inside a pinned pointer?

rosu alin
  • 5,674
  • 11
  • 69
  • 150
  • 1
    There is not a scrap of .NET or C++/CLI code in this snippet. The language extension is called C++/CX, no garbage collector is used and pinning pointers is not meaningful. When you use reinterpret_cast<> then the compiler cannot see that the native code has a reference to the object so it can't emit an AddRef() call to ensure the object stays alive. Storing the object yourself in a static variable or a field of a class that lives long enough is the simple workaround. – Hans Passant Dec 10 '14 at 17:46
  • Sorry, edited it so it says C++/CX. So from what I understood, I don't need to use pinned pointer? I can just save it in a static variable, and use that one? BTW: the class where I need the object is another class, so I do not use it in the same class, is that an issue? – rosu alin Dec 11 '14 at 08:47
  • Find a way to pass the instance as a ^ to the other object. Why do you need a static variable? – CÅdahl Dec 15 '14 at 06:44

2 Answers2

1

There is no garbage collection in C++/CX.

The LmiVideoCapturerWinRTImplementation^ impl variable you defined is a smart pointer type that will automatically manage the lifetime of the object for you. More information on C++/CX types can be found here: http://blogs.msdn.com/b/vcblog/archive/2012/09/17/cxxcxpart02typesthatwearhats.aspx

robwirving
  • 1,790
  • 12
  • 17
  • Thanks, I did a Wrapper, that is a native structure, that keeps the smart pointer inside of it, so it will not be managed automatically – rosu alin Dec 12 '14 at 09:22
  • 1
    Smart pointers play nicely with RAII, by definition, so that shouldn't have to be a problem. (Only if you botch the memory management somehow.) Why not have a ^ in the native structure? It's fine in C++/CX. Alternatively, use Microsoft::WRL::ComPtr. Or, in a pinch, you could cast to a raw IInspectable* and manage the AddRef/Release pairs yourself. – CÅdahl Dec 15 '14 at 06:43
0

Return a T^ instead, or if you need to wrap the T^ in a struct U, just return that U by value.

Avoid raw pointers as far as you can. Don't lose type information by casting to void* either. For a WinRT object, the most you can do safely is to cast to Platform::Object^ or IInspectable*. In the latter case, use ComPtr for storing an owning reference.

CÅdahl
  • 442
  • 3
  • 13