Metatrader и Dll: работаем со строками

Категория: Metatrader
Опубликовано 15.02.2014 15:54

Продолжаем разбираться с передачей данных в dll, на очереди string. Старая статья на эту тему.

Строки обновленного metatrader 4 существенно изменились, теперь они в юникоде и не надо делать никаких преобразований кодировки, что круто. А то, что придется работать с пойнтерами и никак иначе, не очень круто.

Все обьясняющий пример. Mlq4 скрипт:

#property strict 

#import "WindowControl.dll"
	void CallMe(string&);
#import

void OnStart()
{
	string myStr = "00000000000000000";
	CallMe(myStr);
	Print(myStr);
}

Класс-обертка:

using System;
using System.Runtime.InteropServices;
using System.Text;


namespace WindowControl
{
    public 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);
        }

        public void Set(string value)
        {
            byte[] bytes = Encoding.Unicode.GetBytes(value);
            for (int i = 0; i < bytes.Length; i++)
                Marshal.WriteByte(_pointer, i, bytes[i]);
            Marshal.WriteByte(_pointer, bytes.Length, 0);
        }
    }
}

Экспортируемая функция:

using System;
using System.Windows.Forms;


namespace WindowControl
{
    public static class ExportFunctions
    {
        [System.Reflection.Obfuscation(Feature = "DllExport")]
        public static void CallMe(IntPtr pointer)
        {
            MqlString mqlString = new MqlString(pointer);
            MessageBox.Show(mqlString.Get());
            mqlString.Set("ajfkajf");
        }
    }
}

Вот и все, у меня работает. Скорее всего в mql-коде строку предварительно нужно разметить, чтобы она заняла достаточную область памяти. Также не забывайте про интернирование.

Комментарии   

0 # Антон 17.02.2014 23:20
Огромное спасибо!
Работает)
Ответить | Ответить с цитатой | Цитировать
0 # Jonxxx 22.02.2014 16:41
Всегда пожалуйста. :-)
Ответить | Ответить с цитатой | Цитировать
0 # Александр 23.10.2015 13:56
Можно еще строки передавать, используя аттрибут MarshalAs(Unman agedType.BStr). Правда в MT должен поддерживать тип BStr
Ответить | Ответить с цитатой | Цитировать
0 # Валентин 04.12.2015 12:01
Добрый день. Пытаюсь использовать созданную C# dll в Delphi, которую обернул с помощью ExportDll.exe. С передачей и возвратом числовых данных проблем нет. Передать строку из Delphi в C# могу, здесь все ок. А как потом назад вернуть строку из C# в Delphi?
Для передачи и возврата строки в Delphi вызываю так:
function SetGetStr(str: string):string; stdcall; external 'c:\test\Embarc adero\MyTest.dl l';
Ответить | Ответить с цитатой | Цитировать