Modifying array of structures (default marshaling)
Let’s assume you have a user defined structure “EMPLOYEE” in a win32 DLL (let say it “Win32Native.dll”) as shown below.
typedef struct _EMPLOYEE
{
int Age ;
int Sex;
double Salary ;
char* FirstName ;
char* LastName ;
} EMPLOYEE;
Define some functions in native dll (let say it “Win32Native.dll”) as shown below.
extern "C" __declspec(dllexport) void ModifyArrayOfEmployeeStruct(int nSize, EMPLOYEE* pArray);
Implementing Functions
extern "C" __declspec(dllexport) void ModifyArrayOfEmployeeStruct( int nSize, EMPLOYEE* pArray)
{
int result = 0;
EMPLOYEE* pCur = pArray;
STRSAFE_LPSTR temp1, temp2 ;
for ( int i = 0; i < nSize; i++ )
{
size_t nLen1 = 0;
size_t nLen2 = 0;
StringCchLengthA( pCur->FirstName, STRSAFE_MAX_CCH, &nLen1 );
StringCchLengthA( pCur->LastName, STRSAFE_MAX_CCH, &nLen2 );
nLen1 = sizeof(char) * ( nLen1 + 11 ); // To accomodate "<Modified>"
nLen2 = sizeof(char) * ( nLen2 + 11 ); // To accomodate "<Modified>"
temp1 = (STRSAFE_LPSTR)CoTaskMemAlloc( nLen1 );
temp2 = (STRSAFE_LPSTR)CoTaskMemAlloc( nLen2 );
StringCchCopyA( temp1, nLen1, (STRSAFE_LPCSTR)"<Modified>" );
StringCbCatA( temp1, nLen1, (STRSAFE_LPCSTR)pCur->FirstName);
StringCchCopyA( temp2, nLen2, (STRSAFE_LPCSTR)"<Modified>" );
StringCbCatA( temp2, nLen2, (STRSAFE_LPCSTR)pCur->LastName);
// CoTaskMemFree must be used instead of delete to free memory.
CoTaskMemFree( pCur->FirstName );
CoTaskMemFree( pCur->LastName );
pCur->FirstName = (char *)temp1;
pCur->LastName = (char *)temp2;
pCur->Age += 1 ;
pCur->Salary += 1000.0 ;
pCur++;
}
}
Point of Interest
If you want to use a heap that is shared between native and managed, it is more common to use the COM heap.
CoTaskMemAlloc()
and CoTaskMemFree()
.
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
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Employee
{
public int Age;
public int Sex;
public double Salary;
public String FirstName;
public String LastName;
}
class Program
{
[DllImport("Win32Native.dll")]
public static extern int ModifyArrayOfEmployeeStruct(
int nSize,
[In, Out] Employee[] empArr);
static void Main(string[] args)
{
int nCnt = 5; // Number of Items in Structure Array
Employee[] emp = new Employee[nCnt];
emp[0].FirstName = "Ramesh"; emp[0].LastName = "Sharma"; emp[0].Age = 42; emp[0].Salary = 40000; emp[0].Sex = 0;
emp[1].FirstName = "Shalini"; emp[1].LastName = "Verma"; emp[1].Age = 30; emp[1].Salary = 25000; emp[1].Sex = 1;
emp[2].FirstName = "Ramesh"; emp[2].LastName = "Sharma"; emp[2].Age = 51; emp[2].Salary = 35000; emp[2].Sex = 0;
emp[3].FirstName = "Aarushi"; emp[3].LastName = "Shukla"; emp[3].Age = 25; emp[3].Salary = 20000; emp[3].Sex = 0;
emp[4].FirstName = "Malini"; emp[4].LastName = "Kapoor"; emp[4].Age = 33; emp[4].Salary = 30000; emp[4].Sex = 1;
Console.WriteLine("\nEmployee Array Before Call");
for (int nI = 0; nI < nCnt; nI++)
{
StringBuilder sb = new StringBuilder( "First Name=[" );
sb.Append(emp[nI].FirstName);
sb.Append("] Last Name=[");
sb.Append(emp[nI].LastName );
sb.Append("] Age=[");
sb.Append(emp[nI].Age .ToString ());
sb.Append("] Salary=[");
sb.Append(emp[nI].Salary.ToString ("F2"));
sb.Append("] Sex=[");
sb.Append(((emp[nI].Sex == 0) ? "Male" : "Female"));
sb.Append("]");
Console.WriteLine(sb.ToString ());
}
// Call the Function.
ModifyArrayOfEmployeeStruct(emp.Length, emp);
Console.WriteLine("\nEmployee Array After Call");
for (int nI = 0; nI < nCnt; nI++)
{
StringBuilder sb = new StringBuilder("First Name=[");
sb.Append(emp[nI].FirstName);
sb.Append("] Last Name=[");
sb.Append(emp[nI].LastName);
sb.Append("] Age=[");
sb.Append(emp[nI].Age.ToString());
sb.Append("] Salary=[");
sb.Append(emp[nI].Salary.ToString("F2"));
sb.Append("] Sex=[");
sb.Append(((emp[nI].Sex == 0) ? "Male" : "Female"));
sb.Append("]");
Console.WriteLine(sb.ToString());
}
}
}
}
Point of Interest
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