losingsleeep
losingsleeep

Reputation: 1879

type marshaling for working with C++ types

i wanna call a c++ function (in win32 .dll) by C#. the c++ function in like this:

bool pack(BYTE * messageFields[]);

the function wants to fill some data (eg. a string or byte[]) at some indexes of the input argument. so plz tell me how the marshaling should be in C#.NET? i tried many types but got errors or no effects to my parameter!

the C# code must open native .DLL :

[DllImport("c:\\theDllName.dll")]
        public static extern bool pack( // what is here? )

Upvotes: 0

Views: 265

Answers (1)

ds27680
ds27680

Reputation: 1993

System.Byte[] is what you are probably looking for.

Sorry didn'see you had BYTE* ...[].

Some code

extern "C" UNMANAGEDCPP_API int fnUnmanagedCpp(BYTE* test[], int nRows, int nCols)
{
    //do stuff
    std::cout << "called!" << std::endl;

    for ( int i = 0; i < nRows; ++i )
    {
        for ( int j = 0; j < nCols; ++j )
        {
            std::cout << int ( test[i][j] ) << std::endl;
        }
    }

    test[0][0] = 23;

    return 0;
}

And in C#:

   [DllImport("UnmanagedCpp.dll", CallingConvention=CallingConvention.Cdecl)]
   public static extern int fnUnmanagedCpp(IntPtr[] buffer, int nRows, int nCols );

   public static IntPtr[] Marshall2DArray(byte[][] inArray)
   {
       IntPtr[] rows = new IntPtr[inArray.Length];

       for ( int i = 0; i < inArray.Length; ++i )
       {
           rows[i] = Marshal.AllocHGlobal(inArray[i].Length * Marshal.SizeOf(typeof(byte)));
           Marshal.Copy( inArray[i], 0, rows[i], inArray[i].Length );
       }

       return rows;
   }

   public static void Copy2DArray( IntPtr[] inArray, byte[][] outArray )
   {
       Debug.Assert(inArray.Length == outArray.Length);

       int nRows = Math.Min( inArray.Length, outArray.Length );

       for (int i = 0; i < nRows; ++i)
       {
           Marshal.Copy(inArray[i], outArray[i], 0, outArray[i].Length);
       }
   }

   public static void Free2DArray(IntPtr[] inArray)
   {
       for (int i = 0; i < inArray.Length; ++i)
       {
           Marshal.FreeHGlobal(inArray[i]);
       }
   }

    static void Main(string[] args)
    {
        byte[][] bTest = new byte[2][] { new byte[2] { 1, 2 }, new byte[2] { 3, 4 } };

        IntPtr[] inArray = Marshall2DArray(bTest);

        fnUnmanagedCpp(inArray, 2, 2);

        Copy2DArray(inArray, bTest);
        Free2DArray(inArray);

        System.Console.WriteLine(bTest[0][0]);
    }

I hope this helps, maybe there is another better/simpler way to do this. Please note that the code is only for "illustration" and might contain bugs.

Basically one passes in an array of IntPtrs and manually marshals...

Upvotes: 1

Related Questions