Praveen Katiyar' Blog

Learning along the way . . . .

Fetching buffer of numeric types from a Win32 DLL

Define some functions in native dll (let say it “Win32Native.dll”)  as shown below. These 3 functions receives integer buffer, and double buffer respectively.

extern "C" __declspec(dllexport) int FetchIntegerArray ( int nNewSize, int** ppnArray );

extern "C" __declspec(dllexport) double  FetchDoubleArray ( int nNewSize, double ** ppnArray );

Implementing Functions

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

      if ( *ppnArray != NULL ) CoTaskMemFree( *ppnArray );
      *ppnArray = newArray;
      return result;
}

extern "C" __declspec(dllexport) double  FetchDoubleArray ( int nNewSize, double ** ppnArray )
{
     double result = 0;
     //    CoTaskMemAlloc must be used because code on the managed side will call
     //    Marshal.FreeCoTaskMem to free this memory.
     double* newArray = (double*)CoTaskMemAlloc( sizeof(double) * nNewSize );
     for ( int j = 0; j < nNewSize ; j++ )
     {
         newArray[j] = 10 + ( j+1 ) * 30 ;
         result += newArray[j];
     }

     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.Runtime.InteropServices;
using System.Text;

namespace MarshallingTest
{
   class Program
   {
       [DllImport("Win32Native.dll")]
       public static extern int FetchIntegerArray(int nSize, ref IntPtr arrInt);

       [DllImport("Win32Native.dll")]
       public static extern double FetchDoubleArray(int nSize, ref IntPtr arrInt);

       static void Main(string[] args)
       {
           int nSize = 10;
           IntPtr ptrArr = IntPtr.Zero;

           int nSum = FetchIntegerArray(nSize, ref ptrArr);
           int [] arrInt = new int [nSize];
           Marshal.Copy(ptrArr, arrInt, 0, nSize);

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

           for (int i = 0; i < nSize; i++)
           {
               Console.Write("{0:}  ", arrInt[i]);
           }

           Console.Write("\nSum of Integer Buffer : {0}\n", nSum );
           Marshal.FreeCoTaskMem(ptrArr);

           ptrArr = IntPtr.Zero;
          double dblSum = FetchDoubleArray(nSize, ref ptrArr);
          double[] arrDbl = new double[nSize];
          Marshal.Copy(ptrArr, arrDbl, 0, nSize);

          Console.WriteLine("\nReturned Double Buffer\n");
          for (int i = 0; i < nSize; i++)
          {
              Console.Write("{0:F2}  ", arrDbl[i]);
          }

          Console.Write("\nSum of Double Double Buffer : {0}\n", dblSum);
          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

August 3, 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: