C++ Wrapper and Correctly Disposing Unmanaged Resources using ArrayHandle

Posted on

Problem

I have the following class

public class ExrDepthMapExtractor : IDepthMapExtractor
{
    public RawDepthMap GetDepthMap(string filePath)
    {
        return DepthMapExtractorService.ExtractDepthMapAs1DArray(filePath, Callbacks.ProgressCallback);
    }
}

This calls the static C++ API wrapper

public static class DepthMapExtractorService
{
    [DllImport("Blundergat.OpenExr.Adapter.dll", CallingConvention = CallingConvention.Cdecl)]
    [return: MarshalAs(UnmanagedType.I1)]
    private static unsafe extern bool ExtractDepthMapAs1DArray(
        out ItemsSafeHandle vectorHandle,
        out double* points, 
        out int width,
        out int height, 
        string filePath,
        Callbacks.ProgressFunc progressCallback);

    [DllImport("Blundergat.OpenExr.Adapter.dll", CallingConvention = CallingConvention.Cdecl)]
    private static unsafe extern bool Release(IntPtr itemsHandle);

    public static unsafe RawDepthMap ExtractDepthMapAs1DArray(string filePath,
        Callbacks.ProgressFunc progressCallback)
    {
        using (InternalExtractDepthMapAs1DArrayWrapper(filePath, out RawDepthMap rdm, progressCallback))
        {
            rdm.Source = filePath;
            return rdm;
        }
    }

    private static unsafe ItemsSafeHandle InternalExtractDepthMapAs1DArrayWrapper(
        string filePath, out RawDepthMap rdm, Callbacks.ProgressFunc progressCallback)
    {
        double* pixels;
        int width, height;
        ItemsSafeHandle itemsHandle;

        if (!ExtractDepthMapAs1DArray(out itemsHandle, out pixels, out width, out height, filePath, progressCallback))
            throw new InvalidOperationException();

        var pixelList = new List<double>();
        for (int i = 0; i < width * height; i++)
            pixelList.Add(pixels[i]);

        rdm = new RawDepthMap() 
        { 
            Source = filePath, 
            DepthMapArray = pixelList,
            Height = height, 
            Width = width
        };

        return itemsHandle;
    }

    public class ItemsSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        public ItemsSafeHandle() : base(true) { }

        protected override bool ReleaseHandle()
        {
            return Release(handle);
        }
    }
}

In my C++ I Release the ArrayHandle as follows

#include "wrappers.h"

bool ExtractDepthMapAs1DArray(ArrayHandle* arrayHandle,
double** pixels,
int* width,
int* height,
const char* filePath,
ProgressFunc progressCallback)

{
try
{
auto v = new std::vector<double>();
ExrDepthMapExtractor exrExtractor;
*v = exrExtractor.extractDepthMap(filePath, *width, *height, progressCallback);

*arrayHandle = reinterpret_cast<ArrayHandle>(v);
*pixels = v->data();

if (progressCallback != NULL)
{
std::string strFilePath(filePath);
std::string message = "Extracted depth map from "" + strFilePath + """" successfully""

Solution

Leave a Reply

Your email address will not be published. Required fields are marked *