Discussion of article "A DLL for MQL5 in 10 Minutes (Part II): Creating with Visual Studio 2017"

 

New article A DLL for MQL5 in 10 Minutes (Part II): Creating with Visual Studio 2017 has been published:

The original basic article has not lost its relevance and thus if you are interested in this topic, be sure to read the first article. However much time has passed since then, so the current Visual Studio 2017 features an updated interface. The MetaTrader 5 platform has also acquired new features. The article provides a description of dll project development stages, as well as DLL setup and interaction with MetaTrader 5 tools.

Creating a simple DLL

The whole process was already described in the original article. Now we will repeat it taking into account software updates and changes.

Open Visual Studio 2017 and navigate to File -> New -> Project. In the left part of the new project window, expand the Visual C++ list and select Windows Desktop from it. Select the Windows Desktop Wizard line in the middle part. Using entry fields at the bottom part, you can edit the project name (it is advisable to set your own meaningful name) and set project location (it is recommended to keep as suggested). Click OK and proceed to the next window:


Select Dynamic Link Library (.dll) from the drop-down list and check "Export Symbols". Checking this item is optional, but beginners are recommended to do so. In this case, a demo code will be added to the project files. This code can be viewed and then deleted or commented. A click on "OK" creates project files, which can then be edited. However, first we need to consider the project settings. Firstly, remember that MetaTrader 5 only works with 64-bit libraries. If you try to connect a 32-bit DLL, you will receive the following messages:

'E:\...\MQL5\Libraries\Project2.dll' is not 64-bit version
Cannot load 'E:\MetaTrader 5\MQL5\Libraries\Project2.dll' [193]

Thus you will not be able to use this library.

Author: Andrei Novichkov

 

Maybe it will be useful to someone, lately I've been doing it this way:

It is possible (and even easier) to use CodeLight IDE. Compared to Studio, it is fast and less "greedy", it accepts different compilers, including Microsoft's.

To the strange, but DLL using gcc is built easier. In the settings of the DLL project specify the necessary tulchain (gcc32 bit for MT4, gcc64 for MT5). And that's all. Optionally add the command "copy DLL to MT hierarchy" to PostBuild

No fiddling with *.def is unnecessary, def is generated automatically if necessary. By the way, DllMain is unnecessary at all, you can throw it away :-) To be more precise, sometimes it is needed, but very rarely and it is beyond the needs of MT libraries.

 

Another point - not covered in the article, but sought after.

If C++, then perhaps there should be classes, and on both sides, both in Mql and C++.

"dragging a C++ class into Mql".

1. write (or take a ready-made) class :-)

get something like this :

#ifndef  MQLPLUG_H
#define  MQLPLUG_H 1
#include "mql45.h"
/** example of a class that is "dragged" into MT
**/
class Plug {
public:
        Plug();
        ~Plug();

        mql_int OnInit();
        void OnDeinit(mql_int);

        mql_int Sum(mql_int,mql_int);
        mql_double Median(MqlRates *rate);
};
/* since C++ methods cannot be "dragged" through DLL, but only C functions
, simple functions delegating the call to the object
*/ are made.
MQL_API(Plug *) Plug_New();
MQL_API(void) Plug_Delete(Plug *);
MQL_API(mql_int) Plug_OnInit(Plug *);
MQL_API(void) Plug_OnDeinit(Plug *,mql_int);
MQL_API(mql_int) Plug_Sum(Plug *,mql_int,mql_int);
MQL_API(mql_double) Plug_Median(Plug *,MqlRates *rate);
#endif

2. The implementation of "function-delegates" is trivial - the first argument is a pointer to an object, inside the function we should check its correctness, call a method and catch exceptions.

/// MqlPlug.cpp
#include "MqlPlug.h"
/*** wrapper functions of Plug class methods
 all (except _New) receive a pointer to
 object as the first argument. Other arguments are the same as for method
.if the passed pointer is correct (not nullptr), the method
 is called and at the same time all exceptions 
***/ are caught.
/// constructor
MQL_API(Plug *)
Plug_New() {
        try {
                return new Plug;
        } catch (...) {
        }
        return nullptr;
}
/// destructor
MQL_API(void)
Plug_Delete(Plug *plug) {
        try {
                delete plug;
        } catch (...) {
        }
}
// other methods
MQL_API(mql_int)
Plug_Sum(Plug *plug,mql_int one,mql_int two) {
        try {
                if (plug) return plug->Sum(one,two);
        } catch (...) {
        }
        return 0;
}
// и так далее

3. and finally Mql ! In the import directives you describe functions-delegates, and write a class that has a single field obj - a handler (pointer to) the object, and methods calling delegates.

#ifdef __MQL4__
// for 4k the descriptor (pointer) is 32 bits)
#define  HANDLE int
#else
// for a 5 - 64
#define  HANDLE long
#endif

#import "Mql4Plug.dll"
HANDLE Plug_New(void);
void Plug_Delete(HANDLE);
int Plug_OnInit(HANDLE);
void Plug_OnDeinit(HANDLE,const int reason);
int Plug_Sum(HANDLE,int,int);
double Plug_Median(HANDLE,MqlRates &);
#import

class Plug {
public:
   HANDLE obj;
   Plug() {
      obj = Plug_New();
   }
   ~Plug() {
      Plug_Delete(obj);
   }
   int OnInit() {
      if (obj != NULL) {
         return Plug_OnInit(obj);
      }
      return INIT_FAILED;
   }
   void OnDeinit(const int reason) {
      if (obj != NULL) {
         Plug_OnDeinit(obj,reason);
      }
   }
   int Sum(int one,int two) {
      if (obj != NULL) {
         return Plug_Sum(obj,one,two);
      }
      return 0;
   }
   double Median(MqlRates &rates) {
      if (obj!=NULL) {
         return Plug_Median(obj,rates);
      }
      return EMPTY_VALUE;
   }
};

PS/ Once such a request was made and I honestly tried to explain it. But either I was not a very good teacher or my vis-a-vis in programming was not very good :-)) But the popular examples remained - so I'm sharing them

 

Good evening. I'll try to answer everything right away.

Maxim Kuznetsov:
...

No fiddling with *.def is unnecessary, def is generated automatically if necessary. By the way, DllMain is unnecessary at all, you can throw it away :-) To be more precise, sometimes it is needed, but very rarely and it is beyond the needs of MT libraries.

The article is not about how to generate a definition file, whether or not it can be done, what tool to use for it. The article talks about what it is needed for, what it can be used for in VS and what will come out of it. And how to make it, with what and when, it doesn't matter.

About DllMain. Theoretically you are right. Yes, you can do without this function. I know tools where DllMain will not be called even if it is present. But I completely disagree with your categorical conclusion that it is "beyond the boundary". I am convinced that such a conclusion should be made by the developer himself, as he is responsible for the result. If he needs it, he can call something in DllMain. If he doesn't want to, he can write a separate exportable function. Personally, I don't feel competent enough to deprive him of this additional feature so easily.

Maxim Kuznetsov:

Another point - not covered in the article, but in demand.

If C++, then perhaps there should be classes on both sides, both in Mql and C++.

"dragging a C++ class into Mql".

It is absolutely not necessary that there should be class export. )) Thank you for mentioning this feature and special thanks for the example. Personally, it did not occur to me to do something like this and even less to recommend such a technique to novice developers. Look at the artificiality of this code and its irrationality. And what necessity can make a developer handle pointers in such a strange way. In other words, if this code will not crash, it is interesting as a theoretical example, but from the practical point of view - hardly) I will say more, in my opinion, if a developer needs such an export, he is most likely to have made a mistake with the design. Besides, I would like to draw your attention to the fact that about half of the article is devoted to structures, and these are "almost classes". It is worth to stop here and not to follow the footsteps of some of our colleagues from the forum who would gladly shove all C++17 into MQL )).

 

I'm not arguing with you ;-)

just some notes that came to mind, maybe someone will find it useful.

without arguing with the article

what kind of"novice programmers" are there at the junction of two languages ?

PS/ by the way, you have a long memory there :-)

 
Maxim Kuznetsov:

I'm not arguing with you ;-)

so - some notes that I remembered, maybe it will be useful to someone.

Thank you, it will be useful.

but unfortunately such good examples are very often in forum topics, it is very difficult to find them, alas, I sin myself )))).

If you are not lazy, you should put such excellent examples in your blog, at least there is some probability that you will find them faster, but it is also not a fact (((( - MQL has amazing possibilities, but sometimes it is faster to google it yourself and find a ready example... by the way, this forum is very well indexed by google, almost all queries on the topic of neural networks will result in MQL articles ;)

 
Maxim Kuznetsov:

I'm not arguing with you ;-)

so - some notes that I remembered, maybe it will be useful to someone.

without arguing with the article

what kind of"novice programmers" are there at the junction of two languages ?

PS/ by the way, you have a lot of memory there.

What's with the memory, did I mess up somewhere?

Beginner programmer is a stretching concept ) I am definitely a beginner in Python ) Or in java script. And many other things I can call myself a beginner in. Here too, what kind of situation is there, if a person hasn't made libraries before, but has been doing CAD for twenty years, or writing plugins for Adobe programs? Of course, he is a beginner in a new field, but experienced in his old one. Anyway, it's all right, this terminology is not so important here.

 
Can i create custom menus within Metatrader with a c++ dll?
 
No)
 
Thanks for the article. Is there a sequel planned for VS 2022 with the backlog of changes?
 
There are no plans for now