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



我正在用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;
}

我的问题是,当从MQL4调用HistoricMarketData时,它不起作用。该脚本要么导致整个MetaTrader程序崩溃,要么引发异常并失败。

正如您所看到的,我正在使用Robert Giesecke的Unmanaged Exports库使其工作,并且我正确地将DLL导入到MQL4,因为里面的其他函数都在正常工作,没有任何问题。

经过大量的尝试和错误,我发现当我从结构中删除这两个字符串属性(symboltime)时,所有的工作都如预期的那样,并且结构正确地传递给了C#函数。

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

我已经尝试将结构中MarshalAs注释处的UnmanagedType参数更改为其他字符串变体,但没有帮助。将CCD_ 17改为CCD_。

如果有任何建议或帮助,我将不胜感激。

谢谢!

欢迎来到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导入的函数

但魔鬼隐藏在这样的细节中(间接禁止功能):


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

最新更新