Discussão do artigo "Como escrever uma biblioteca DLL em MQL5 (Parte II) em 10 minutos: escrevendo no ambiente do Visual Studio 2017"
Talvez isso seja útil para alguém, pois ultimamente tenho feito dessa forma:
É possível (e até mais fácil) usar o IDE CodeLight. Comparado ao Studio, ele é rápido e menos "ganancioso", aceita diferentes compiladores, inclusive o da Microsoft.
É estranho, mas a DLL usando o gcc é criada com mais facilidade. Nas configurações do projeto DLL, especifique o tulchain necessário (gcc32 bit para MT4, gcc64 para MT5). E isso é tudo. Opcionalmente, adicione o comando "copy DLL to MT hierarchy" ao PostBuild
Não é necessário mexer no *.def, pois ele é gerado automaticamente, se necessário. A propósito, o DllMain é desnecessário, você pode jogá-lo fora :-) Para ser mais preciso, às vezes ele é necessário, mas muito raramente e está além das necessidades das bibliotecas MT.
Outro ponto - não abordado no artigo, mas muito procurado.
Se for C++, talvez devam existir classes, e em ambos os lados, tanto em Mql quanto em C++.
"arrastar uma classe C++ para o Mql".
1. escrever (ou pegar uma classe pronta) :-)
obter algo como isto:
#ifndef MQLPLUG_H #define MQLPLUG_H 1 #include "mql45.h" /** exemplo de uma classe que é "arrastada" para o 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); }; /* Como os métodos C++ não podem ser "arrastados" pela DLL, mas somente as funções C , são criadas funções simples que delegam a chamada ao objeto */. 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. A implementação de "delegados de função" é trivial: o primeiro argumento é um ponteiro para um objeto; dentro da função, devemos verificar sua correção, chamar um método e capturar exceções.
/// MqlPlug.cpp #include "MqlPlug.h" /*** funções de wrapper dos métodos da classe Plug todas (exceto _New) recebem um ponteiro para o objeto como primeiro argumento. Os outros argumentos são os mesmos do método .Se o ponteiro passado estiver correto (não nullptr), o método será chamado e, ao mesmo tempo, todas as exceções ***/ serão capturadas. /// construtor MQL_API(Plug *) Plug_New() { try { return new Plug; } catch (...) { } return nullptr; } /// Destruidor MQL_API(void) Plug_Delete(Plug *plug) { try { delete plug; } catch (...) { } } // outros métodos 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. e, finalmente, Mql! Nas diretivas de importação, você descreve funções-delegadas e escreve uma classe que tem um único campo obj - um manipulador (ponteiro para) o objeto e métodos que chamam delegados.
#ifdef __MQL4__ // para 4k, o descritor (ponteiro) é de 32 bits) #define HANDLE int #else // para um 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/ Uma vez foi feita uma solicitação desse tipo e eu tentei explicá-la honestamente. Mas ou eu não era um professor muito bom ou minha visão de programação não era muito boa :-)) Mas os exemplos populares permaneceram, por isso estou compartilhando-os
Boa noite. Tentarei responder a tudo imediatamente.
...
Não é necessário mexer no *.def, pois ele é gerado automaticamente, se necessário. A propósito, o DllMain é desnecessário, você pode jogá-lo fora :-) Para ser mais preciso, às vezes ele é necessário, mas muito raramente e está além das necessidades das bibliotecas MT.
O artigo não trata de como gerar um arquivo de definição, se isso pode ou não ser feito, qual ferramenta usar para isso. O artigo fala sobre o que é necessário, para que pode ser usado no VS e o que resultará dele. E como fazer isso, com o que e quando, não importa.
Sobre o DllMain. Teoricamente, você está certo. Sim, você pode passar sem essa função. Conheço ferramentas em que a DllMain não será chamada, mesmo que esteja presente. Mas discordo totalmente de sua conclusão categórica de que ela está "além do limite". Estou convencido de que essa conclusão deve ser feita pelo próprio desenvolvedor, pois ele é responsável pelo resultado. Se ele precisar, poderá chamar algo em DllMain. Se não quiser, ele pode escrever uma função exportável separada. Pessoalmente, não me sinto competente o suficiente para privá-lo desse recurso adicional tão facilmente.
Outro ponto, que não foi abordado no artigo, mas que está sendo solicitado.
Se for C++, talvez deva haver classes em ambos os lados, tanto em Mql quanto em C++.
"arrastar uma classe C++ para o Mql".
Não é absolutamente necessário que haja exportação de classes. )) Obrigado por mencionar esse recurso e um agradecimento especial pelo exemplo. Pessoalmente, não me ocorreu fazer algo assim e muito menos recomendar essa técnica a desenvolvedores novatos. Observe a artificialidade desse código e sua irracionalidade. E que necessidade pode levar um desenvolvedor a lidar com ponteiros de uma forma tão estranha. Em outras palavras, se esse código não travar, ele é interessante como exemplo teórico, mas do ponto de vista prático - dificilmente). Vou dizer mais: na minha opinião, se um desenvolvedor precisar dessa exportação, é muito provável que ele tenha cometido um erro no projeto. Além disso, gostaria de chamar sua atenção para o fato de que cerca de metade do artigo é dedicada a estruturas, e essas são "quase classes". Vale a pena parar por aqui e não seguir os passos de alguns de nossos colegas do fórum, que gostariam de colocar todo o C++17 na MQL )).
Não estou discutindo com você ;-)
apenas algumas observações que me vieram à mente, talvez alguém as ache úteis.
sem discutir com o artigo
que tipo de"programadores novatos" existem na junção de duas linguagens?
PS/ a propósito, você tem uma memória longa :-)
Não estou discutindo com você ;-)
então - algumas anotações de que me lembrei, talvez sejam úteis para alguém.
Obrigado, será útil.
Mas, infelizmente, esses bons exemplos estão frequentemente em tópicos de fóruns, é muito difícil encontrá-los, infelizmente, eu mesmo me sinto culpado )))).
Se você não for preguiçoso, deveria colocar esses excelentes exemplos em seu blog, pelo menos há alguma probabilidade de encontrá-los mais rapidamente, mas isso também não é um fato (((( - o MQL tem possibilidades incríveis, mas às vezes é mais rápido pesquisar no Google e encontrar um exemplo pronto... a propósito, este fórum é muito bem indexado pelo Google, quase todas as consultas sobre o tópico de redes neurais resultarão em artigos sobre MQL ;)
Não estou discutindo com você ;-)
então - algumas anotações de que me lembrei, talvez sejam úteis para alguém.
sem discutir com o artigo
que tipo de"programadores novatos" existem na junção de duas linguagens?
PS/ a propósito, você tem muita memória aí.
O que há com a memória, eu errei em algum lugar?
Programador iniciante é um conceito que está se esticando) Eu sou definitivamente um iniciante em Python) ou em java script. E em muitas outras coisas em que posso me considerar um iniciante. Aqui também, que tipo de situação existe, se uma pessoa nunca criou bibliotecas antes, mas está trabalhando com CAD há vinte anos ou escrevendo plugins para programas da Adobe? É claro que ele é um iniciante em um novo campo, mas experiente em seu antigo. De qualquer forma, está tudo bem, essa terminologia não é tão importante aqui.
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
Novo artigo Como escrever uma biblioteca DLL em MQL5 (Parte II) em 10 minutos: escrevendo no ambiente do Visual Studio 2017 foi publicado:
O artigo básico inicial não perdeu sua importância e todos os interessados neste tópico simplesmente devem lê-lo. Mas já se passou muito tempo desde então, e agora o Visual Studio 2017 com uma nova interface está à frente, também a própria plataforma MetaTrader 5 vem se desenvolvendo e segue em frente. O artigo descreve as etapas de criação de um projeto dll, abrangendo configurações e colaboração com as ferramentas do terminal MetaTrader 5.
Criando uma DLL simples
Esta travessia já foi totalmente concluída no artigo inicial, aqui vamos repeti-la, considerando as mudanças acumuladas.
No ambiente do Visual Studio 2017, selecionamos File -> New -> Project. Na janela que aparece, à esquerda, abrimos a lista do Visual C++ e selecionamos Windows Desktop e, na parte intermediária, selecionamos a linha Windows Desktop Wizard. Na parte inferior existem vários campos de entrada onde você pode alterar o nome (é recomendável definir seu próprio) e a localização do projeto (é melhor deixá-lo como sugerido). Tudo está pronto, clicamos em "OK" e vamos para a próxima janela:
Aqui é preciso selecionar Dynamic Link Library (.dll) na lista suspensa e marcar o item "Export Symbols". Na verdade, marcar este item é opcional, mas é de preferência para desenvolvedores iniciantes. Neste caso, um código de demonstração é adicionado aos arquivos do projeto, eles podem ser visualizados e depois excluídos ou comentados. Clicamos no botão "OK" para criar os arquivos de projeto, que podemos editar a seguir. No entanto, é muito cedo para fazer isso antes de descobrirmos as configurações do projeto. Em primeiro lugar, é preciso lembrar que o MetaTrader 5 só funciona com bibliotecas de 64 bits. Se tentarmos anexar uma de 32 bits, obteremos as seguintes mensagens:
'E:\...\MQL5\Libraries\Project2.dll' is not 64-bit version
Cannot load 'E:\MetaTrader 5\MQL5\Libraries\Project2.dll' [193]
Por conseguinte, é impossível trabalhar assim.
Autor: Andrei Novichkov