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 structure
} MyComplexType;
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(BYTE* pArray, int size)
{
for (int i=0; i< size; i++)
printf("%d\n", pArray[i]);
}
void MyFunction2(MyComplexType* myComplexType)
{
myComplexType->X = 100;
myComplexType->Y = 200;
myComplexType->Z = 300;
for (int i = 0; i < 10; i++) {
myComplexType->MyFixedArray[i] = i * 5;
}
}
void MyFunction3(MyComplexType** myComplexType, int 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** pArray, int 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(BYTE* pArray, int size)
{
for (int i=0; i< size; i++)
pArray[i] = i * 5;
}
void MyFunction7(BYTE** pArray, int* size)
{
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([In, Out]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