Praveen Katiyar' Blog

Learning along the way . . . .

Modifying array of string values (default Marshaling)

Define some functions in native dll (let say it “Win32Native.dll”)  as shown below. this function receives array of char pointers (string).

extern "C" __declspec(dllexport) void ModifyStringArrayValues( int nCount, char* ppStrArray[] )

Implementing Functions

extern "C" __declspec(dllexport) void ModifyStringArrayValues( int nCount, char* ppStrArray[] )
{
    size_t cchDest = 40;
    const size_t alloc_size = sizeof(char) * 40;
    for ( int nI = 0; nI < nCount; nI++ )
    {
        char *pszFormat = "<<from DLL>> [Modified String %2d]";
        STRSAFE_LPSTR temp = (STRSAFE_LPSTR)CoTaskMemAlloc( alloc_size );
        StringCchPrintfA(temp, cchDest, pszFormat, nI);
        CoTaskMemFree( ppStrArray[nI] );
        ppStrArray[nI] = (char *) temp;
   }
}

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.
  • StringCchPrintfA printf used to print a formatted output to a string buffer.

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 double ModifyStringArrayValues(int nSize, [In, Out] String[] strArr);
    
        static void Main(string[] args)
        {
            int nSize = 5;
            string[] arrStr = new string[nSize];
            for (int nI = 0; nI < nSize; nI++) arrStr[nI] = "String " + (nI + 1).ToString();

           
            Console.WriteLine("String Values in Array, before calling function");
            for (int i = 0; i < nSize; i++)
            {
                Console.WriteLine(string.Format("Array[{0:D2}] : {1}", i, arrStr[i]));
            }

            ModifyStringArrayValues(nSize, arrStr);

            Console.WriteLine("String Values in Array, after calling function");
            for (int i = 0; i < nSize; i++)
            {
                Console.WriteLine(string.Format("Array[{0:D2}] : {1}", i, arrStr[i]));
            }
        }
    }
}

Point of Interest

  • namespace System.Runtime.InteropServices;  defines the declarations necessary for Interop operations, like DllImport,
  • DllImport defines the DLL entry point.

compile and execute you will get following output.

image

Advertisements

August 6, 2013 - Posted by | .NET, CodeProject, Interoperability, 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: