How to correctly pass array of structs from MQL4 script to C# DLL library

 

I am writing a script in MQL4 language for Metatrader 4 which is using C# DLL library for further data processing.

 

What I'm trying to do is to pass an array of following MQL structures:

struct marketUpdate
{    
    double openPrice;
    double closePrice;
    double highPrice;
    double lowPrice;
    int volume;
    double pipValuePerLot;
    int intervalLength;
    string symbol;
    string time;
};

 to this function in C# DLL:

[DllExport("HistoricMarketData", CallingConvention.StdCall)]
public static int HistoricMarketData(
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] MarketUpdate[] unmanagedArray,
    int length)
{
    // further processing
}

 This is the function definition on MQL side:

 int HistoricMarketData(
          marketUpdate &marketUpdates[],
          int length);

 and this is the structure on C# side:

[StructLayout(LayoutKind.Explicit)]
public struct MarketUpdate
{
    [MarshalAs(UnmanagedType.R8)]
    [FieldOffset(0)]
    public double openPrice;

    [MarshalAs(UnmanagedType.R8)]
    [FieldOffset(8)]
    public double closePrice;

    [MarshalAs(UnmanagedType.R8)]
    [FieldOffset(16)]
    public double highPrice;

    [MarshalAs(UnmanagedType.R8)]
    [FieldOffset(24)]
    public double lowPrice;

    [MarshalAs(UnmanagedType.I4)]
    [FieldOffset(32)]
    public int volume;

    [MarshalAs(UnmanagedType.R8)]
    [FieldOffset(36)]
    public double pipValuePerLot;

    [MarshalAs(UnmanagedType.I4)]
    [FieldOffset(44)]
    public int intervalLength;

    [MarshalAs(UnmanagedType.LPWStr)]
    [FieldOffset(48)]
    public string symbol;

    [MarshalAs(UnmanagedType.LPWStr)]
    [FieldOffset(60)]
    public string time;
}

 

My problem is that it is not working when calling HistoricMarketData from MQL. The script either crashes whole Metatrader program or throws an exception and fails.

As you can see I'm using Robert Giesecke's Unmanaged Exports library to make it works and I correctly imported DLL to MQL as other functions inside are working without any issue.

After lot of trial and error I was able to find out that when I remove those 2 string attributes (symbol and time) from structure all works as expected and structure is correctly passed to C# function.

So my question is how to correctly pass string in structure from MQL to C#?

I already tried to change UnmanagedType parameter at MarshalAs annotation in structure to other string variants but it didn't help. It also didn't help to change string to char[] on both sides.

I'll appreciate any advices or help.

Thanks!
 

Old topic but no answers on the internet yet. Here it comes:


Way less complicated. You use IntPtr within C# and declare the import-section with the struct. Thats it. To copy the data you use memcpy() of msvcrt.dll. 

[DllExport("Whatever_with_struct", CallingConvention = CallingConvention.StdCall)]
    public static void Whatever_with_struct(IntPtr structData, int structSize)
        {
        }

and within MQL

struct mystruct 
        {
        double d1;
        int i1;
        long l1;
        }
#import "mydll.dll"
void Whatever_with_struct (mystruct &data, int size);
#import

mystruct mydata;
Whatever_with_struct(mydata,sizeof(mystruct));

In case the struct is the same in C# and MQL, you dont even need the sizeof() term. 
And of course that works with MQL5 and MQL4. Just compile the DLL separately for 64 and 32 bit.