如何正确地将结构数组从MQL4传递到C#DLL库

时间:2016-08-03 13:26:47

标签: c# dll unmanaged mql4

我正在使用 MQL4 语言为MetaTrader Terminal 4编写一个脚本,该脚本使用 C#DLL库进行进一步的数据处理。

我要做的是传递一组以下MQL4 - 结构:

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

C# DLL中的此功能:

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

这是MQL4方面的功能定义:

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

这是C#方面的结构:

[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;
}

我的问题是,从HistoricMarketData致电MQL4时,它无效。该脚本要么崩溃整个MetaTrader程序,要么抛出异常而失败。

正如您所看到的,我正在使用Robert Giesecke的非托管导出库来使其正常工作,并且我正确地将DLL导入MQL4,因为内部的其他功能无需任何工作问题。

经过大量的反复试验后,我发现当我从结构中删除这两个字符串属性(symboltime)时,所有工作都按预期工作,并且结构正确传递给{{ 1}}功能。

所以我的问题是如何正确地将结构中的字符串从C#传递到MQL4

我已经尝试将结构C#注释中的UnmanagedType参数更改为其他字符串变体,但它没有帮助。将双方的MarshalAs更改为string也无济于事。

我会感激任何建议或帮助。

谢谢!

1 个答案:

答案 0 :(得分:2)

欢迎来到MQL4的野外世界,其中string不是字符串,而是struct

所以,
对此,
而不仅仅是这个,
重新整合MQL4DLL - s

引起了很大的麻烦

我自己的策略是:

1)避免MQL4 - 字符串,如果不是核心重要性,
2)如果需要,通过DLL代理实用程序函数传递它们,该函数处理所需的转换:

#import <dll>                                        // DLL-native CallSignatures: 
...
int          mql4s_send ( int socket, uchar &text[] );
...
#import
                                                     // DLL-proxy with  StringToCharArray() conversion:
int              s_send ( int socket, string text ) { uchar textChar[]; StringToCharArray( text, textChar );
    return ( mql4s_send (     socket,                       textChar ) );
  }

无论如何,更确切地说,阅读MQL4帮助,在每次MetaTrader Build更新后再次更好地重新阅读(是的,我说,新的帮助文件包含(至少)对新MQL4 - 功能的一些评论,没有其他简单的方法可以找到和了解 - 它节省了大量的时间。在维护代码库的情况下,跨越了几百人*年,我非常了解疼痛。)

  

以下内容不能用于导入功能中的参数:
  ·指针;
  ·链接到包含动态数组和/或指针的对象   
  包含字符串和/或任何类型的动态数组的类,字符串数组或复杂对象不能作为参数传递作为从DLL导入的函数的参数。

但是Devil隐藏在这样的细节中(间接禁止的特征):

  

...
  简单结构   
  包含动态数组的字符串或对象的结构称为简单结构;这些结构的变量可以自由地相互复制,即使它们是不同的结构。简单结构的变量以及它们的数组可以作为参数传递给从DLL导入的函数。