无法从 DLL

问题描述

我尝试使用 glitch100/BinanceDotNet 库在 C# 中从 Binance API 获取总余额,并进行了一些修改(例如将这些数据成员从 private 到 public static)

这样做的目的是由 MQL5 函数调用以供 MT5 使用

我的 DLL 的 C# 代码有点像这样:

using System;
using System.Text;
using RGiesecke.DllExport;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO.Pipes;
using System.IO;
using BinanceExchange.API.Client;

namespace BinanceAPIConnectMetaTrader
{
    class Program
    {

        public static string DataServerReturn = null;

        [DllExport("APIFetchTotalFreeBalance",CallingConvention = CallingConvention.StdCall)]
        public static IntPtr APIFetchTotalFreeBalance(int _AccountType,IntPtr _ApiKey,IntPtr _SecretKey)
        {
            if (_AccountType == 0)
            {
                BinanceExchange.API.Endpoints.APIPrefix = "https://api.binance.com/api";
                BinanceExchange.API.Endpoints.WAPIPrefix = "https://api.binance.com/wapi";
                BinanceExchange.API.Websockets.AbstractBinanceWebSocketClient.BaseWebsocketUri = "wss://stream.binance.com:9443/ws";
                BinanceExchange.API.Websockets.AbstractBinanceWebSocketClient.CombinedWebsocketUri = "wss://stream.binance.com:9443/stream?streams";
            }
            else
            {
                BinanceExchange.API.Endpoints.APIPrefix = "https://testnet.binance.vision/api";
                BinanceExchange.API.Endpoints.WAPIPrefix = "https://testnet.binance.vision/wapi";
                BinanceExchange.API.Websockets.AbstractBinanceWebSocketClient.BaseWebsocketUri = "wss://testnet.binance.vision/ws";
                BinanceExchange.API.Websockets.AbstractBinanceWebSocketClient.CombinedWebsocketUri = "wss://testnet.binance.vision/stream?streams";
            }

            decimal total_free_balance = 0.0M;
            
            string apiKey = new MqlString(_ApiKey).Get();
            string secretKey = new MqlString(_SecretKey).Get();

            //Initialise the general client with config
            var client = new BinanceClient(new ClientConfiguration()
            {
                ApiKey = apiKey,SecretKey = secretKey,});

            
            try
            {
                client.GetAccount@R_962_4045@ion(3500).Result.Balances.ForEach(k =>
                {
                   total_free_balance += k.Free;
                });
            
            }
            catch (Exception ex)
            {
                string str = "Exception from dll : " + ex.Message;
                return Marshal.StringToHGlobalAuto(str.ToString());
            }
            
            IntPtr ret = Marshal.StringToHGlobalAuto(total_free_balance.ToString());
            return ret;
        }

    }

    public class StreamString
    {
        private Stream ioStream;
        private UnicodeEncoding streamEncoding;

        public StreamString(Stream ioStream)
        {
            this.ioStream = ioStream;
            streamEncoding = new UnicodeEncoding();
        }

        public string ReadString()
        {
            int len;
            len = ioStream.ReadByte() * 256;
            len += ioStream.ReadByte();
            byte[] inBuffer = new byte[len];
            ioStream.Read(inBuffer,len);

            return streamEncoding.GetString(inBuffer);
        }

        public int WriteString(string outString)
        {
            byte[] outBuffer = streamEncoding.GetBytes(outString);
            int len = outBuffer.Length;
            if (len > UInt16.MaxValue)
            {
                len = (int)UInt16.MaxValue;
            }
            ioStream.WriteByte((byte)(len / 256));
            ioStream.WriteByte((byte)(len & 255));
            ioStream.Write(outBuffer,len);
            ioStream.Flush();

            return outBuffer.Length + 2;
        }
    }

    class MqlString
    {
        private readonly IntPtr _pointer;

        public MqlString(IntPtr pointer)
        {
            _pointer = pointer;
        }

        public string Get()
        {
            int size;

            for (int i = 0; ; i += 2)
            {
                if (Marshal.ReadByte(_pointer,i) == 0)
                {
                    size = i;
                    break;
                }
            }

            byte[] bytes = new byte[size];

            for (int i = 0; i < size; i++)
            {
                bytes[i] = Marshal.ReadByte(_pointer,i);
            }

            return Encoding.Unicode.GetString(bytes);
        }
    }
}

  1. 调用函数时,会捕获异常并显示消息如下:
Total free balance = Exception from dll : One or more errors occurred.
  1. 删除try关键字及其大括号并注释掉catch块内部后,当调用函数时,MT5端日志消息中会显示一些有趣的运行时异常,如下所示:
Unhandled exception 0xE0434352
              00007FFE51603AC0 4881ECD8000000    sub        rsp,0xd8
              00007FFE51603AC7 488B0562732200    mov        rax,[rip+0x227362]
              00007FFE51603ACE 4833C4            xor        rax,rsp
              00007FFE51603AD1 48898424C0000000  mov        [rsp+0xc0],rax
              00007FFE51603AD9 488364242800      and        qword [rsp+0x28],0x0
              00007FFE51603ADF 488D05DAFFFFFF    lea        rax,[rip-0x26]
              00007FFE51603AE6 83E201            and        edx,0x1
              00007FFE51603AE9 894C2420          mov        [rsp+0x20],ecx
              00007FFE51603AED 89542424          mov        [rsp+0x24],edx
              00007FFE51603AF1 4889442430        mov        [rsp+0x30],rax
              00007FFE51603AF6 4D85C9            test       r9,r9
              00007FFE51603AF9 744B              jz         0x7ffe51603b46
              
              00007FFE51603AFB B80F000000        mov        eax,0xf
              00007FFE51603B00 488D4C2440        lea        rcx,[rsp+0x40]
              00007FFE51603B05 443BC0            cmp        r8d,eax
              00007FFE51603B08 498BD1            mov        rdx,r9
              00007FFE51603B0B 440F47C0          cmova      r8d,eax
              00007FFE51603B0F 4489442438        mov        [rsp+0x38],r8d
              00007FFE51603B14 49C1E003          shl        r8,0x3
              00007FFE51603B18 E84AD30400        call       0x7ffe51650e67  ; PublisherFromPackageFullName (kernelbase.dll)
              00007FFE51603B1D 488D4C2420        lea        rcx,[rsp+0x20]
              00007FFE51603B22 48FF15FF441600    call       qword near [rip+0x1644ff]  ; UnhandledExceptionFilter (kernelbase.dll)
   crash -->  00007FFE51603B29 0F1F440000        nop        [rax+rax+0x0]
              00007FFE51603B2E 488B8C24C0000000  mov        rcx,[rsp+0xc0]
              00007FFE51603B36 4833CC            xor        rcx,rsp
              00007FFE51603B39 E8A25E0400        call       0x7ffe516499e0  ; RemoveDllDirectory (kernelbase.dll)
              00007FFE51603B3E 4881C4D8000000    add        rsp,0xd8
              00007FFE51603B45 C3                ret        

              00007FFE51603B46 8364243800        and        dword [rsp+0x38],0x0

00: 0x00007FFE51603B29

我真的不知道这是什么以及如何解决它。

这段代码是有问题的部分(但是当作为 EXE 构建时它可以正常工作,就像在 glitch100/BinanceDotNet/BinanceExchange.Console/ExampleProgram.cs 的 GitHub 页面中一样)

client.GetAccount@R_962_4045@ion(3500).Result.Balances.ForEach(k =>
{
    total_free_balance += k.Free;
});

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)