tags:

views:

164

answers:

2

I have a C api and I am using p/invoke to call a function from the api in my C# application. The function signature is:

int APIENTRY GetData (CASHTYPEPOINTER cashData);

Type definitions:

typedef CASHTYPE* CASHTYPEPOINTER;

typedef struct CASH
{
 int CashNumber;
 CURRENCYTYPE Types[24];
} CASHTYPE;   

typedef struct CURRENCY
{
 char Name[2];
 char NoteType[6];
 int NoteNumber;
} CURRENCYTYPE;

How would be my C# method signature and data types?

Thank you.

A: 

I think it may look like this

      using System.Runtime.InteropServices;

        [StructLayout(LayoutKind.Sequential)]
        public struct CASH{
            public int CashNumber; 
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)]
            public CURRENCY Types[24];
        }   

    [ StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
        public struct CURRENCY {
             [MarshalAs( UnmanagedType.ByValTStr, SizeConst=2 )]
             public string Name;
             [MarshalAs( UnmanagedType.ByValTStr, SizeConst=6 )]
             public string NoteType;
             public int NoteNumber;
        }   

        class Wrapper {
            [DllImport("my.dll")]
            public static extern int GetData(ref CASH cashData}
        }
Ahmed Said
sorry, I forgot to add MarshalAs attribute CURRENCYTYPE array!!
Ahmed Said
You also reference the type CURRENCYTYPE (from CASH) but have only defined CURRENCY. I believe that the C structs from the question should be CASHTYPE and CURRENCYTYPE.
Johan Kullbom
another typo, I fixed it
Ahmed Said
+3  A: 

You need to specify the array sizes using SizeConst:

using System;
using System.Runtime.InteropServices;

public static class MyCApi
{
    [StructLayout(LayoutKind.Sequential)]
    public struct CASHTYPE
    {
        public int CashNumber;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)]
        public CURRENCYTYPE[] Types;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct CURRENCYTYPE
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
        public string Name;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
        public string NoteType;
        public int NoteNumber;
    }

    [DllImport("MyCApi.dll")]
    public static extern int GetData(ref CASHTYPE cashData);
}
Johan Kullbom
it works perfectly, thank you
frameworkninja