Quantcast
Channel: .NET Framework Class Libraries forum
Viewing all articles
Browse latest Browse all 8156

Managed class to wrap unmanaged memory

$
0
0

I want to call a series of C++ methods, typically with the output of one C++ method being the input to the next.  For performance reasons, I do not want to marshal the data back and forth on every call but instead keep all the memory in unmanaged space - these are really large arrays.  Now the obvious answer is: write one method in C++ that calls all the methods.  However, I want more control from the C#/managed side - sometimes saving intermediate results.

I wrote an UmanagedArray class that inherits from SafeHandle.  I have a protected IntPtr called 'UnmanagedPtr'.  I added a float[] property which gets and sets an array of float data, which I would use only to get data into unmanaged memory and extract it out, as such:

        // float* AllocateAndFillArray(float* data, int length)
        [DllImport(DLLPath, CallingConvention = CallingConvention.Cdecl)]
        private static extern IntPtr AllocateAndFillArray(float[] data, int length);

        // void CopyUnmanagedToManaged(float * data, float *result, int length)
        [DllImport(DLLPath, CallingConvention = CallingConvention.Cdecl)]
        private static extern void CopyUnmanagedToManaged(IntPtr input, float[] result, int length);

        // void FreeArray(void * array)
        [DllImport(DLLPath, CallingConvention = CallingConvention.Cdecl)]
        private static extern void FreeArray(IntPtr data);

...

public float[] Data { get { if (UnmanagedPtr == IntPtr.Zero) { return new float[0]; } float[] result = new float[Length]; CopyUnmanagedToManaged(UnmanagedPtr, result, Length * sizeof(float)); return result; } set { if (UnmanagedPtr != IntPtr.Zero) { FreeArray(UnmanagedPtr); UnmanagedPtr = IntPtr.Zero; Length = 0; } if ((value != null) && (value.Length > 0)) { UnmanagedPtr = AllocateAndFillArray(value, value.Length * sizeof(float)); Length = value.Length; } } }

The C++ code:

extern "C" __declspec(dllexport) void FreeArray(void * array) {
	free(array);
}

extern "C" __declspec(dllexport) void* AllocateAndFillArray(void* data, size_t length) {
	void *memptr = (float*)malloc(length * sizeof(float));
	memcpy(memptr, data, length);
	return memptr;
}

extern "C" __declspec(dllexport) void CopyUnmanagedToManaged(void* data, void* result, size_t length) {
	memcpy(result, data, length);
}

This works fine.  My issue is this: I want to make a generic UnmanagedArray<T>{} class that can manage arrays (1-D and 2-D) of any value type - int, long, float, double for starters.  Is there any way to do this?  Using void* in the C++ side works fine when declared in C# as float[].  I can't figure out how to overload the DLLImport to accommodate any type.


Viewing all articles
Browse latest Browse all 8156

Trending Articles