My Blog

Passing complex data between C and C#

by lupok on mercoledì 28 agosto 2013 00:53

A series of examples that show how to pass complex data (structures or arrays) from C# to C


PassingStructArrayBetweenCandCSharp.h

 

#define DLL_EXPORT __declspec(dllexport#pragma pack(1)
typedef struct {
   int X;
   int Y;
   int Z;
   int MyFixedArray[10]; // if you want to use an array with size is not fixed you may use the SAFEARRAY structureMyComplexType;
 
extern "C"
{
 
   // Pass a Byte array from C# to C
   DLL_EXPORT void __cdecl MyFunction1(BYTE* pArray, int size);
 
   // Pass a data structure from C# to C
   DLL_EXPORT void __cdecl MyFunction2(MyComplexType* myComplexType);
 
   // Pass an array of structures from C# to C function which internally assigns a value to each element of the structure. 
   DLL_EXPORT void __cdecl MyFunction3(MyComplexType** myComplexType, int arraySize);
 
   // Pass an array of byte from C# to C function which internally assigns a value to each element of the array. 
   DLL_EXPORT void __cdecl MyFunction4(BYTE** pArray, int size);
 
   // C function that returns an array of strings
   DLL_EXPORT char** __cdecl MyFunction5();
 
   // Pass an array of byte from C# to C function which internally assigns a value to each element of the array. 
   DLL_EXPORT void __cdecl MyFunction6(BYTE* pArray, int size);
 
   // Pass a byte array from C # to a C function that internally creates the array and assigns a value to each element of it
   DLL_EXPORT void __cdecl MyFunction7(BYTE** pArray, int* size);
}

 

 

PassingStructArrayBetweenCandCSharp.cpp

 

#include "stdafx.h"
#include "PassingStructArrayBetweenCandCSharp.h"
#include <stdio.h></stdio.h>
 
void MyFunction1(BYTEpArrayint size)
{
   for (int i=0; i< size; i++)
      printf("%d\n"pArray[i]);
}
 
void MyFunction2(MyComplexTypemyComplexType)
{
   myComplexType->X = 100;
   myComplexType->Y = 200;
   myComplexType->Z = 300;
 
   for (int i = 0; i < 10; i++) {
      myComplexType->MyFixedArray[i] = i * 5;   
   }
}
 
void MyFunction3(MyComplexType** myComplexTypeint arraySize)
{
   for (int i = 0; i < arraySize; i++) {
 
      (*myComplexType)->X = 101 * (i + 1);
      (*myComplexType)->Y = 202 * (i + 1);
      (*myComplexType)->Z = 303 * (i + 1);
 
      for (int j = 0; j < 10; j++) {
         (*myComplexType)->MyFixedArray[j] = j * (i + 1);
      }
 
      myComplexType++;
   }
}
 
void MyFunction4(BYTE** pArrayint size)
{
   for (int i=0; i< size; i++){
      **pArray = i * 7;
      pArray++;
   }      
}
 
char** MyFunction5()
{
    static char* myArray[3] = {"first""second""third",};
 
    return myArray;
}
 
void MyFunction6(BYTEpArrayint size)
{
   for (int i=0; i< size; i++)
      pArray[i] = i * 5;
}
 
void MyFunction7(BYTE** pArrayintsize)
{
   BYTE* array = new BYTE[7];
 
   for (int i = 0; i < 7; i++) {
      array[i] = i * 9;
      
   }
 
   *pArray = array;
   *size = 7;
 
}

 

 

Program.cs

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
 
namespace TestPassingStructArrayBetweenCandCSharp
{
   class Program
   {
      [StructLayout(LayoutKind.Sequential, Pack = 1)]
      struct MyComplexType
      {
         public int X;
         public int Y;
         public int Z;
         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
         public int[] MyFixedArray;
      }
 
      [DllImport("PassingStructArrayBetweenCandCSharp.dll",
         EntryPoint = "MyFunction1", CallingConvention = CallingConvention.Cdecl)]
      public static extern void MyFunction1(IntPtr pArray, int nSize);
 
      [DllImport("PassingStructArrayBetweenCandCSharp.dll",
         EntryPoint = "MyFunction2", CallingConvention = CallingConvention.Cdecl)]
      static extern int MyFunction2(ref MyComplexType points);
 
      [DllImport("PassingStructArrayBetweenCandCSharp.dll",
         EntryPoint = "MyFunction3", CallingConvention = CallingConvention.Cdecl)]
      static extern int MyFunction3(IntPtr[] myComplexTypeArray, int arraySize);
 
      [DllImport("PassingStructArrayBetweenCandCSharp.dll",
         EntryPoint = "MyFunction4", CallingConvention = CallingConvention.Cdecl)]
      static extern int MyFunction4(IntPtr[] myByteArray, int arraySize);
 
      [DllImport("PassingStructArrayBetweenCandCSharp.dll",
         EntryPoint = "MyFunction5", CallingConvention = CallingConvention.Cdecl)]
      private static extern IntPtr MyFunction5();
 
      [DllImport("PassingStructArrayBetweenCandCSharp.dll",
         EntryPoint = "MyFunction6", CallingConvention = CallingConvention.Cdecl)]
      public static extern void MyFunction6([InOut]IntPtr pArray, int arraySize);
 
      [DllImport("PassingStructArrayBetweenCandCSharp.dll",
        EntryPoint = "MyFunction7", CallingConvention = CallingConvention.Cdecl)]
      public static extern void MyFunction7(ref IntPtr pArray, ref int pArraySize);
 
      static void Main(string[] args)
      {
 
         // MyFunction1
 
         Byte[] array = new Byte[10];
 
         Random random = new Random();
         for (int i = 0; i < array.Length; i++)
         {
            array[i] = (Byte)random.Next(Byte.MaxValue);
         }
 
         int size = Marshal.SizeOf(array[0]) * array.Length;
         IntPtr pnt = Marshal.AllocHGlobal(size);
 
         Marshal.Copy(array, 0, pnt, array.Length);
 
         MyFunction1(pnt, array.Length);
 
         Marshal.FreeHGlobal(pnt);
 
         // MyFunction2
 
         MyComplexType myComplexType = new MyComplexType();
 
         MyFunction2(ref myComplexType);
 
         Console.WriteLine("Simple data: X = {0}, Y = {1}, Z = {2}",
            myComplexType.X, myComplexType.Y, myComplexType.Z);
 
         for (int y = 0; y < myComplexType.MyFixedArray.Length; ++y)
            Console.WriteLine("FixedArray item: {0}, value: {1}", y,
               myComplexType.MyFixedArray[y]);
 
         // MyFunction3
 
         int arraySize = 10;
 
         IntPtr[] pMyComplexTypeArray = new IntPtr[arraySize];
 
         for (int i = 0; i < arraySize; i++)
            pMyComplexTypeArray[i] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MyComplexType)));
 
         MyFunction3(pMyComplexTypeArray, arraySize);
 
         MyComplexType[] myComplexTypeArray = new MyComplexType[arraySize];
 
         for (int i = 0; i < arraySize; i++)
            myComplexTypeArray[i] =
               (MyComplexType)Marshal.PtrToStructure(pMyComplexTypeArray[i], typeof(MyComplexType));
 
         for (int i = 0; i < arraySize; i++)
            Marshal.FreeHGlobal(pMyComplexTypeArray[i]);
 
 
         for (int i = 0; i < arraySize; i++)
         {
            Console.WriteLine("Struct {0}, Simple data: X = {1}, Y = {2}, Z = {3}", i,
               myComplexTypeArray[i].X, myComplexTypeArray[i].Y, myComplexTypeArray[i].Z);
 
            for (int y = 0; y < myComplexTypeArray[i].MyFixedArray.Length; ++y)
               Console.WriteLine("FixedArray item: {0}, value: {1}", y,
                  myComplexTypeArray[i].MyFixedArray[y]);
         }
 
         // MyFunction4
 
         int byteArraySize = 10;
 
         IntPtr[] pByteArray = new IntPtr[byteArraySize];
 
         for (int i = 0; i < byteArraySize; i++)
            pByteArray[i] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Byte)));
 
         MyFunction4(pByteArray, byteArraySize);
 
         Byte[] myByteArray = new Byte[byteArraySize];
 
         for (int i = 0; i < byteArraySize; i++)
            myByteArray[i] = Marshal.ReadByte(pByteArray[i]);
 
         for (int i = 0; i < byteArraySize; i++)
            Marshal.FreeHGlobal(pByteArray[i]);
 
 
         for (int i = 0; i < byteArraySize; i++)
         {
            Console.WriteLine("Byte: {0}, Value: {1}", i, myByteArray[i]);
         }
 
 
         // MyFunction5
 
         string[] returnArray = new string[3];
 
         for (int i = 0; i < returnArray.Length; i++)
            returnArray[i] = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(MyFunction5(), 4 * i));
 
         for (int i = 0; i < returnArray.Length; i++)
         {
            Console.WriteLine("String: {0}, Value: {1}", i, returnArray[i]);
         }
 
         // MyFunction6
 
         Byte[] array6 = new Byte[10];
 
         IntPtr pArray6 = Marshal.AllocHGlobal(Marshal.SizeOf(array6[0]) * array6.Length);
 
         MyFunction6(pArray6, array6.Length);
 
         Marshal.Copy(pArray6, array6, 0, array6.Length);
 
         for (int i = 0; i < array6.Length; i++)
         {
            Console.WriteLine("Array6[{0}], Value: {1}", i, array6[i]);
         }
 
         Marshal.FreeHGlobal(pArray6);
 
         // MyFunction7
 
         IntPtr pArray7 = IntPtr.Zero;
         int array7Size = 0;
 
         MyFunction7(ref pArray7, ref array7Size);
 
         Byte[] array7 = new Byte[array7Size];
 
         Marshal.Copy(pArray7, array7, 0, array7.Length);
 
         for (int i = 0; i < array7.Length; i++)
         {
            Console.WriteLine("Array7[{0}], Value: {1}", i, array7[i]);
         }
 
         // !! WARNING !!
         // In this example, the C function creates an array is allocated in unmanaged memory and will have to provide a means to free up memory.
 
      }
   }
}

 

PassingStructArrayBetweenCandCSharp.zip

Blogs Parent Separator My Blog
Author
lupok

My Blog

Tags