Modifying array of numeric types (default Marshaling)
Define some functions in native dll (let say it “Win32Native.dll”) as shown below. These 2 functions receives integer buffer, and double buffer respectively.
extern "C" __declspec(dllexport) int ModifyIntegerArrayValues ( int nSize, int* pArray)
extern "C" __declspec(dllexport) double ModifyDoubleArrayValues ( int nSize, double* pArray)
Implementing Functions
extern "C" __declspec(dllexport) int ModifyIntegerArrayValues ( int nSize, int* pArray)
{
int nResult = 0 ;
for ( int i = 0; i < nSize; i++ )
{
nResult += pArray[ i ];
pArray[i] += 100;
}
return nResult;
}
extern "C" __declspec(dllexport) double ModifyDoubleArrayValues ( int nSize, double* pArray)
{
double dblResult = 0 ;
for ( int i = 0; i < nSize; i++ )
{
dblResult += pArray[ i ];
pArray[i] += 200 ;
}
return dblResult ;
}
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.
- On the native side use
CoTaskMemAlloc()
andCoTaskMemFree()
. - On the managed side use
Marshal.AllocCoTaskMem()
andMarshal.FreeCoTaskMem()
.
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 void ModifyIntegerArrayValues(int nCount, [In, Out] int[] arrStr);
[DllImport("Win32Native.dll")]
public static extern int ModifyDoubleArrayValues(int nSize, [In, Out] double[] nArr);
static void Main(string[] args)
{
int nSize = 5 ;
int[] arrInt = new int[nSize];
for (int nI = 0; nI < nSize; nI++) arrInt[nI] = (nI + 1) * 10;
Console.WriteLine("\nValues of Integer array, before calling function");
for (int i = 0; i < nSize; i++)
{
Console.WriteLine(string.Format("Array[{0:D2}] : {1:D3}", i, arrInt[i]));
}
ModifyIntegerArrayValues(nSize, arrInt);
Console.WriteLine("\nValues of Integer array, after calling function");
for (int i = 0; i < nSize; i++)
{
Console.WriteLine(string.Format("Array[{0:D2}] : {1:D3}", i, arrInt[i]));
}
double [] arrDbl= new double [nSize];
for (int nI = 0; nI < nSize; nI++) arrDbl[nI] = (nI + 1) * 5.0 ;
Console.WriteLine("\nValues of Double array, before calling function");
for (int i = 0; i < nSize; i++)
{
Console.WriteLine(string.Format("Array[{0:D2}] : {1:F2}", i, arrDbl[i]));
}
ModifyDoubleArrayValues(nSize, arrDbl);
Console.WriteLine("\nValues of double array, after calling function");
for (int i = 0; i < nSize; i++)
{
Console.WriteLine(string.Format("Array[{0:D2}] : {1:F2}", i, arrDbl[i]));
}
}
}
}
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.
No comments yet.
-
Archives
- April 2014 (2)
- November 2013 (1)
- October 2013 (4)
- September 2013 (4)
- August 2013 (6)
- July 2013 (8)
- June 2013 (1)
-
Categories
-
RSS
Entries RSS
Comments RSS
Leave a comment