Передача структуры в dll C++

 

Пишу dll, которая будет выполнять логику, и собственно возник вопрос. Можно ли передавать в dll структуру данных?

Т.е. мне нужно создать свою собственную структуру, которую я бы принимал я своей dll написанной на С++. Планируются 2 структуры:
1) отправка параметров робота

2) отправка котировок

Если с котировками все понятно, можно просто по ссылкам массивы типа double, то параметры я хотел бы получать как структуру а не как элементы... 

Есть ли способ выполнить подобную стыковку ? сколько ищу информацию, не как не могу найти не чего на эту тему.

 
AndreyKrivcov:

Пишу dll, которая будет выполнять логику, и собственно возник вопрос. Можно ли передавать в dll структуру данных?

Т.е. мне нужно создать свою собственную структуру, которую я бы принимал я своей dll написанной на С++. Планируются 2 структуры:
1) отправка параметров робота

2) отправка котировок

Если с котировками все понятно, можно просто по ссылкам массивы типа double, то параметры я хотел бы получать как структуру а не как элементы... 

Есть ли способ выполнить подобную стыковку ? сколько ищу информацию, не как не могу найти не чего на эту тему.

Не пробовал.

Я гоняю в ДЛЛ всю инфу туда-сюда через CSV- строки, и не заморачиваюсь. Быстродействие с учетом шифровки-дешифровки >1.5ГБайт/с - Хватит на все, и даже останется.))

ЗЫ И еще, все однотипно, и никакого зоопарка решений.

 
AndreyKrivcov:

Можно ли передавать в dll структуру данных?

Ответ в документации:

Структуры, которые не содержат строки, объекты класса, указатели и объекты динамических массивов, называются простыми структурами. Переменные простых структур, а также их массивы можно передавать в качестве параметров в импортируемые из DLL функции.


Было бы неплохо увидеть обновленную версию этой статьи где будет показана работа со структурами.

Как за 10 минут написать DLL библиотеку для MQL5 и обмениваться данными?
Как за 10 минут написать DLL библиотеку для MQL5 и обмениваться данными?
  • 2010.01.27
  • MetaQuotes
  • www.mql5.com
Так уж сложилось, что сейчас мало кто из разработчиков помнит, как написать простую DLL библиотеку и в чем особенности связывания разнородных систем. Я постараюсь за 10 минут на примерах показать весь процесс создания простых DLL библиотек и раскрою некоторые технические детали нашей реализации связывания. Демонстрация будет на примере Visual...
 
Andrey Voytenko:

Ответ в документации:


Было бы неплохо увидеть обновленную версию этой статьи где будет показана работа со структурами.


Как я понял, строки передавать нельзя, а вот массив char (не динамический а с выделеной памятью) передавать вполне можно, верно ?

 
AndreyKrivcov:

Как я понял, строки передавать нельзя, а вот массив char (не динамический а с выделеной памятью) передавать вполне можно, верно ?

Да, просто заменяете string на статические массивы char или short(для строк Unicode).

 
Andrey Voytenko:

Да, просто заменяете string на статические массивы char.


Благодарю

 
Andrey Voytenko:

Ответ в документации:


Было бы неплохо увидеть обновленную версию этой статьи где будет показана работа со структурами.


А можно ли передать массив структур ? И соответственно получить массив структур назад ? 

Пытаюсь это сделать, код в самой dll рабочий (проверял через консольное приложение), однако когда передаю массив из Mql5 то тогда он не передается как следует и не возвращается (один массив передаю, другой пытаюсь получить по ссылке)

 
AndreyKrivcov:

А можно ли передать массив структур ? И соответственно получить массив структур назад ? 

Пытаюсь это сделать, код в самой dll рабочий (проверял через консольное приложение), однако когда передаю массив из Mql5 то тогда он не передается как следует и не возвращается (один массив передаю, другой пытаюсь получить по ссылке)

можете показать код?

 
Andrey Voytenko:

можете показать код?

Dll:


Header:

#pragma once
#include <string>

#define _TO_MQL_ extern "C" __declspec(dllexport)

struct Quotes
{
        char* Symb;
        double bid;
        double ask;
        double last;
        double open;
        double high;
        double low;
        double close;
        long volume;
        long tickVolume;
        int timeFrame;
        unsigned long DT;
};

struct QuotesArr
{
        unsigned int size;
        Quotes * quote_data;
};

struct TOrders_ans
{
        char * Symb;
        int lot;
        double SL, TP, Order;
};

_TO_MQL_ bool Cpp_callRobot(QuotesArr * arr, int row, TOrders_ans *orders, int *orders_row);


Cpp:

#include "Header.h"
#include<io.h>
#include<fstream>
#include<ctime>
#include <Windows.h>

#include <direct.h>

//#pragma hdstop
//#pragma argsused


std::string path = "C:\\Users\\Андрей\\Desktop\\Test Mql5.txt";

BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
        return(TRUE);
}

_TO_MQL_ bool Cpp_callRobot(QuotesArr * arr, int row, TOrders_ans * orders, int * orders_row)
{
        std::ofstream out;
        if (_access(path.c_str(), 0) == -1)
                out = std::ofstream(path.c_str());
        else
                out = std::ofstream(path.c_str(), std::ios::app);
        out << "Cpp_callRobot" << std::endl;

        bool ans = false;
        if (arr != nullptr)
        {
                ans = true;

                for (int i = 0; i < row; i++)
                {
                        out << (int)arr[i].size << std::endl;
                        for (int j = 0; j < (int)arr[i].size; j++)
                        {
                                out << "i =" << i << " | j = " << j << std::endl;
                                std::string symb = arr[i].quote_data[j].Symb;
                                std::string S = symb + ";" + std::to_string(arr[i].quote_data[j].bid) + ";" + std::to_string(arr[i].quote_data[j].ask) + ";" +
                                        std::to_string(arr[i].quote_data[j].last) + ";" + std::to_string(arr[i].quote_data[j].open) + ";" + std::to_string(arr[i].quote_data[j].high) + ";" +
                                        std::to_string(arr[i].quote_data[j].low) + ";" + std::to_string(arr[i].quote_data[j].close) + std::to_string(arr[i].quote_data[j].volume) + ";" +
                                        std::to_string(arr[i].quote_data[j].tickVolume) + ";" + std::to_string(arr[i].quote_data[j].timeFrame) + ";" + std::to_string(arr[i].quote_data[j].DT);
                                out << S << std::endl;
                        }
                }

                (*orders_row) = 2;
                for (int i = 0; i < 2; i++)
                {
                        std::string symb = "Symb_";
                        orders[i].lot = i;
                        orders[i].Order = i + 1;
                        orders[i].SL = i + 2;
                        orders[i].TP = i + 3;
                        orders[i].Symb = (char*)symb.c_str();
                }

        }
        out.close();
        return ans;
}
 

Тест из консоли:

#include "..\Test Mql5Connector\Header.h"
#include<iostream>

int main()
{
        QuotesArr *arr = new QuotesArr[2];
        for (int i = 0; i < 2; i++)
        {
                arr[i].quote_data = new Quotes[3];
                arr[i].size = 3;
                for (int j = 0; j < 3; j++)
                {
                        arr[i].quote_data[j].ask = i;
                        arr[i].quote_data[j].bid = j;
                        arr[i].quote_data[j].close = i;
                        arr[i].quote_data[j].DT = j;
                        arr[i].quote_data[j].high = i;
                        arr[i].quote_data[j].last = j;
                        arr[i].quote_data[j].low = i;
                        arr[i].quote_data[j].open = j;
                        arr[i].quote_data[j].Symb = (char*)("Symb" + std::to_string(i)).c_str();
                        arr[i].quote_data[j].tickVolume = j;
                        arr[i].quote_data[j].timeFrame = i;
                        arr[i].quote_data[j].volume = j;
                }
        }

        TOrders_ans *ans = new TOrders_ans[2];

        int rows;

        if (Cpp_callRobot(arr, 2, ans, &rows))
        {
                for (int i = 0; i < rows; i++)
                {
                        std::cout << "lot = " << ans[i].lot << " | Order = " << ans[i].Order
                                << " | SL = "<< ans[i].SL << " | Symb = " << ans[i].Symb << " | TP = " << ans[i].TP << std::endl;
                }
        }

        return 0;
}
 

Тест из MT5


struct Quotes
  {
   char              Symb[10];
   double            bid;
   double            ask;
   double            last;
   double            open;
   double            high;
   double            low;
   double            close;
   long              volume;
   long              tickVolume;
   int               timeFrame;
   unsigned long     DT;
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct QuotesArr
  {
   unsigned int      size;
   Quotes            quote_data[3];
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct TOrders_ans
  {
   char              Symb[10];
   int               lot;
   double            SL,TP,Order;
  };

#import "Test Mql5Connector.dll"
bool Cpp_callRobot(QuotesArr &arr[],int row,TOrders_ans &orders[],int &orders_row);
#import
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---

   string Symb=_Symbol;

   


   QuotesArr arr[2];
   TOrders_ans orders[2];
//ArrayInitialize(arr);

   for(int i=0;i<2;i++)
     {
      arr[i].size=3;
      ArrayResize(arr[i].quote_data,3,3);
      for(int j=0;j<3;j++)
        {
         MqlTick tickData[];
         if(i==1)
            Symb="Si-3.18";

         CopyTicks(Symb,tickData);
         StringToCharArray(Symb,arr[i].quote_data[j].Symb);
         arr[i].quote_data[j].DT=tickData[0].time;
         arr[i].quote_data[j].ask = tickData[0].ask;
         arr[i].quote_data[j].bid = tickData[0].bid;
         arr[i].quote_data[j].timeFrame=1;
         arr[i].quote_data[j].volume=(long)tickData[0].volume;
         arr[i].quote_data[j].last=tickData[0].last;

         long tickVol[];
         CopyTickVolume(Symb,PERIOD_CURRENT,0,1,tickVol);
         arr[i].quote_data[j].tickVolume=tickVol[0];

         double price[];
         CopyClose(Symb,PERIOD_CURRENT,0,1,price);
         arr[i].quote_data[j].close=price[0];
         ArrayFree(price);

         CopyOpen(Symb,PERIOD_CURRENT,0,1,price);
         arr[i].quote_data[j].open=price[0];
         ArrayFree(price);

         CopyHigh(Symb,PERIOD_CURRENT,0,1,price);
         arr[i].quote_data[j].high=price[0];
         ArrayFree(price);

         CopyLow(Symb,PERIOD_CURRENT,0,1,price);
         arr[i].quote_data[j].low=price[0];
         ArrayFree(price);
        }
     }

   int orders_row;


   if(Cpp_callRobot(arr,2,orders,orders_row))
     {
      Print("Cpp_callRobot returned true");
      for(int i=0;i<orders_row;i++)
        {
         string S = CharArrayToString(orders[i].Symb);
         Print(S+" data || SL: "+orders[i].SL+" || TP: "+orders[i].TP+" || Order: "+orders[i].Order+" || lot: "+orders[i].lot);
        }
     }
  }