rosasurfer / mt4-expander

DLL extension for the MetaTrader4 MQL framework
Do What The F*ck You Want To Public License
35 stars 28 forks source link

Can you turn ShiftIndicatorBuffer into a template #6

Closed Janaue closed 2 years ago

Janaue commented 2 years ago

I want to use the ShiftIndicatorBuffer from the dll rsfMT4Expander.dll

https://github.com/rosasurfer/mt4-expander/blob/47dbb1a57439b233117f7b141c6b4b010f39e57a/src/util/helper.cpp

/**
 * Shifted die Werte eines IndicatorBuffers um eine Anzahl von Bars nach hinten. Die ältesten Werte verfallen.
 *
 * @param  double buffer[]   - MQL-Double-Array (IndicatorBuffer)
 * @param  int    bufferSize - Größe des Arrays
 * @param  int    bars       - Anzahl der zu shiftenden Bars
 * @param  double emptyValue - Initialisierungswert für freiwerdende Bufferelemente
 *
 * @return BOOL - Erfolgsstatus
 **/

BOOL WINAPI ShiftIndicatorBuffer(double buffer[], int bufferSize, int bars, double emptyValue) {
   if (buffer && (uint)buffer < MIN_VALID_POINTER) return(error(ERR_INVALID_PARAMETER, "invalid parameter buffer = 0x%p (not a valid pointer)", buffer));
   if (bufferSize < 0)                             return(error(ERR_INVALID_PARAMETER, "invalid parameter bufferSize = %d", bufferSize));
   if (bars < 0)                                   return(error(ERR_INVALID_PARAMETER, "invalid parameter bars = %d", bars));
   if (!bufferSize || !bars) return(TRUE);

   MoveMemory((void*)&buffer[0], &buffer[bars], (bufferSize-bars)*sizeof(buffer[0]));

   for (int i=bufferSize-bars; i < bufferSize; i++) {
      buffer[i] = emptyValue;
   }
   return(TRUE);
   #pragma EXPANDER_EXPORT
}

but I a big number of buffers and I have various types of buffers, like ''char'' , ''long'' and so on so I really need a template for this. So instead of only ''double'', ShiftIndicatorBuffer(double buffer[], int bufferSize, int bars, double emptyValue) would take any type of buffer and MQL will do whatever it has to do to make sens of it.

rosasurfer commented 2 years ago

Thank you for your interest. This is a C++ DLL which is loaded at runtime. At runtime the MetaTrader terminal looks up exported functions only by name. Function overloading via templates is a compiler feature of C++, it's not possible for exported functions at runtime. To implement ShiftIndicatorBuffer() for different parameter types it needs a different function name per type. In other words: You cannot export function templates from a DLL. However you may use a template in your MQL code to reference the various implementations exported from the DLL.

You referenced an old commit from 2017 which is very outdated. Please have a look at the current implementation for integers and doubles in the master branch:

https://github.com/rosasurfer/mt4-expander/blob/master/src/lib/array.cpp

rosasurfer commented 2 years ago

Rewriting the functions using templates to support MQL5 data types in the development branch. Once finished the changes will show up in master.

https://github.com/rosasurfer/mt4-expander/blob/development/src/lib/array.cpp

Janaue commented 2 years ago

OK I was coming from https://www.mql5.com/en/forum/217490#comment_5918810 because the behavior for offline chart is just insane. He says ''While it is possible to implement it in MQL for performance reasons it is strongly recommended to move the code to a DLL where memory can be moved directly without using loops:'' but since I cant get template with functions from a DLL, I am willing to try the approach with poor performance. However I don't know how to code this in MQL `MoveMemory((void)&buffer[0], &buffer[count], (size-count)sizeof(buffer[0]));

std::fill_n(&buffer[size-count], count, emptyValue);`

Can you give the MQL equivalent to your DLL trick, ideally as a template?

rosasurfer commented 2 years ago

This is me on mql5.com (a long time ago, I'm not active there anymore), and using the DLL without template functions is perfectly fine. You just use separate imports. Look at the development branch, there are now functions for all MQL5 data types. Currently I'm testing the behavior for unsigned data types.

Compiled DLL in this directory: https://github.com/rosasurfer/mt4-mql/tree/development/mql4/libraries

Import declarations: https://github.com/rosasurfer/mt4-mql/blob/0ecc35da8b80b9a6300e15238c1479987d282f78/mql4/include/api.mqh#L946

#import "rsfMT4Expander.dll"
   // ...insert what you need from api.mqh
#import

At the moment everything is still in development branches and subject to change. After finishing of work changes will show up in the master branches.

rosasurfer commented 2 years ago

Changes are merged to master: array.cpp, api.mqh, DLL (notice the Download button)

Following an example using an int[] array:

ShiftIntIndicatorBuffer ShiftIntIndicatorBuffer DebugView

An actual usage example can be seen in my custom ZigZag indicator. It uses the global variable ShiftedBars which was mentioned at the mql5.com forum.