Praveen Katiyar' Blog

Learning along the way . . . .

Fetching a byte buffer from a Win32 DLL

 

Define  a function in native dll (let say it “Win32Native.dll”)  as shown below.

extern "C" __declspec(dllexport) int FetchByteArray ( int nSize, byte** ppnArray )
{
    int result = 0;
    //    CoTaskMemAlloc must be used instead of the new operator because code on the managed side will call
    //    Marshal.FreeCoTaskMem to free this memory.
    byte* newArray = (byte*)CoTaskMemAlloc( sizeof(byte) * nSize );
    for ( int j = 0; j < nNewSize ; j++ )
    {
        newArray[j] = ( j+1 ) % 255 ;
        result += newArray[j];
    }

    // release the previous buffer, if any allocated.
    if ( *ppnArray != NULL ) CoTaskMemFree( *ppnArray );
    *ppnArray = newArray;
    return result;
}

Point of Interest
  • CoTaskMemAlloc is used to allocated the memory required.
  • CoTaskMemFree is used to free any previously allocated buffer, if null is passed then, CoTaskMemFree is not called.

If you want to use a heap that is shared between native and managed, it is more common to use the COM heap.

Writing the client code (the managed part)

one can simple create a console base application which can use this dll. let’s name it MarshallingTest.

see the code snippet below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace MarshallingTest
{
    class Program
    {
        [DllImport("Win32Native.dll")]
        public static extern int FetchByteArray(int nSize, ref IntPtr arrInt);
    
        static void Main(string[] args)
        {
            int nSize = 10;
            IntPtr ptrArr = IntPtr.Zero;

            int nSum = FetchByteArray(nSize, ref ptrArr);
            byte[] arrByte = new byte[nSize];
            Marshal.Copy(ptrArr, arrByte, 0, nSize);

            Console.WriteLine("\nReturned Buffer\n");

            for (int i = 0; i < nSize; i++)
            {
                Console.Write ( "{0:D2}  ", arrByte[i] );
            }
           
            Console.Write("\nSum of Buffer : {0}\n", nSum );
            Marshal.FreeCoTaskMem(ptrArr);
        }
    }
}

Point of Interest
  • namespace System.Runtime.InteropServices;  defines the declarations necessary for Interop operations, like DllImport,
  • DllImport defines the DLL entry point.
  • Marshal.Copy function used to copy buffer from managed buffer to unmanaged buffer and vice versa.
  • Marshal.FreeCoTaskMem frees the memory allocated by native DLL.

compile and execute you will get following output.

image

Advertisements

July 31, 2013 - Posted by | .NET, CodeProject, Interoperability, Marshaling, Win32 | , , ,

No comments yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: