Add mql4-lib dependencies directly; change header comments on license; fix ZmqMsg setData method bug
This commit is contained in:
@@ -0,0 +1,242 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Module: Lang/GlobalVariable.mqh |
|
||||
//| This file is part of the mql4-lib project: |
|
||||
//| https://github.com/dingmaotu/mql4-lib |
|
||||
//| |
|
||||
//| Copyright 2017 Li Ding <dingmaotu@126.com> |
|
||||
//| |
|
||||
//| Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
//| you may not use this file except in compliance with the License. |
|
||||
//| You may obtain a copy of the License at |
|
||||
//| |
|
||||
//| http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
//| |
|
||||
//| Unless required by applicable law or agreed to in writing, |
|
||||
//| software distributed under the License is distributed on an |
|
||||
//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
|
||||
//| either express or implied. |
|
||||
//| See the License for the specific language governing permissions |
|
||||
//| and limitations under the License. |
|
||||
//+------------------------------------------------------------------+
|
||||
#property strict
|
||||
//+------------------------------------------------------------------+
|
||||
//| Encapsulates global variable functions |
|
||||
//+------------------------------------------------------------------+
|
||||
class GlobalVariable
|
||||
{
|
||||
public:
|
||||
static int total() {return GlobalVariablesTotal();}
|
||||
static string name(int index) {return GlobalVariableName(index);}
|
||||
static void flush() {GlobalVariablesFlush();}
|
||||
|
||||
static bool exists(string name) {return GlobalVariableCheck(name);}
|
||||
static datetime lastAccess(string name) {return GlobalVariableTime(name);}
|
||||
|
||||
static bool makeTemp(string name) {return GlobalVariableTemp(name);}
|
||||
static double get(string name) {return GlobalVariableGet(name);}
|
||||
static bool get(string name,double &value) {return GlobalVariableGet(name,value);}
|
||||
static datetime set(string name,double value) {return GlobalVariableSet(name,value);}
|
||||
static bool setOn(string name,double value,double check) {return GlobalVariableSetOnCondition(name,value,check);}
|
||||
|
||||
static bool remove(string name) {return GlobalVariableDel(name);}
|
||||
static bool removeAll(string prefix=NULL,datetime before=0) {return GlobalVariablesDeleteAll(prefix,before);}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| TempVar is a variable whose life time is the same as the program |
|
||||
//+------------------------------------------------------------------+
|
||||
class TempVar
|
||||
{
|
||||
private:
|
||||
string m_name;
|
||||
bool m_owned;
|
||||
public:
|
||||
TempVar(string name,bool create=false):m_name(name),m_owned(create)
|
||||
{
|
||||
if(create)
|
||||
{
|
||||
GlobalVariable::makeTemp(name);
|
||||
}
|
||||
}
|
||||
~TempVar() {if(m_owned && isValid()) {GlobalVariable::remove(m_name);}}
|
||||
|
||||
bool isValid() const {return GlobalVariable::exists(m_name);}
|
||||
string getName() const {return m_name;}
|
||||
bool set(double value) {return GlobalVariable::set(m_name,value);}
|
||||
double get() const {return GlobalVariable::get(m_name);}
|
||||
bool setOn(double value,double check) {return GlobalVariable::setOn(m_name,value,check);}
|
||||
datetime lastAccess() const {return GlobalVariable::lastAccess(m_name);}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class AtomicVar: public TempVar
|
||||
{
|
||||
public:
|
||||
AtomicVar(string name,long initial,bool create=false):TempVar(name,create)
|
||||
{
|
||||
set(initial);
|
||||
}
|
||||
long increment(long by=1);
|
||||
long decrement(long by=1) {return increment(-by);}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
long AtomicVar::increment(long by)
|
||||
{
|
||||
bool success=false;
|
||||
long value;
|
||||
do
|
||||
{
|
||||
value=(long)get();
|
||||
success=setOn(value+by,value);
|
||||
}
|
||||
while(!success);
|
||||
return (value+by);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class Semaphore
|
||||
{
|
||||
private:
|
||||
TempVar m_var;
|
||||
public:
|
||||
Semaphore(string name,long initial=0);
|
||||
bool isValid() const {return m_var.isValid();}
|
||||
bool acquire();
|
||||
void release();
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
Semaphore::Semaphore(string name,long initial)
|
||||
:m_var(name,initial!=0)
|
||||
{
|
||||
if(initial!=0)
|
||||
{
|
||||
m_var.set(initial);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool Semaphore::acquire(void)
|
||||
{
|
||||
bool success=false;
|
||||
do
|
||||
{
|
||||
long value=(long)m_var.get();
|
||||
if(value == 0) return false;
|
||||
success=m_var.setOn(value-1,value);
|
||||
}
|
||||
while(!success && !IsStopped());
|
||||
return success;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void Semaphore::release(void)
|
||||
{
|
||||
bool success=false;
|
||||
do
|
||||
{
|
||||
long value=(long)m_var.get();
|
||||
success=m_var.setOn(value+1,value);
|
||||
}
|
||||
while(!success && !IsStopped());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| CriticalSection object for making atomic operations |
|
||||
//| |
|
||||
//| An exmaple of creating a global context (the creation and destroy|
|
||||
//| are both enclosed between the SAME critical section): |
|
||||
//| |
|
||||
//| enter() |
|
||||
//| if(refcount==0) create context |
|
||||
//| else refcontext |
|
||||
//| increase refcount |
|
||||
//| leave() |
|
||||
//| |
|
||||
//| enter() |
|
||||
//| decrease refcount |
|
||||
//| if(refcount==0) context destroy |
|
||||
//| leave() |
|
||||
//+------------------------------------------------------------------+
|
||||
class CriticalSection
|
||||
{
|
||||
private:
|
||||
const string m_name;
|
||||
public:
|
||||
CriticalSection(string name):m_name(name){}
|
||||
|
||||
bool isValid() const {return m_name!=NULL;}
|
||||
string getName() const {return m_name;}
|
||||
|
||||
void enter() { while(!GlobalVariable::makeTemp(m_name) && !IsStopped())Sleep(100); }
|
||||
bool tryEnter() { return GlobalVariable::makeTemp(m_name); }
|
||||
void leave() { GlobalVariable::remove(m_name);}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| A reference counted global pointer (or handle) |
|
||||
//| Generic type parameter T can be long or int depending the handle |
|
||||
//| length (64bit or 32bit) |
|
||||
//| HandleManager should implement 2 static methods: create & destroy|
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename T,typename HandleManager>
|
||||
class GlobalHandle
|
||||
{
|
||||
private:
|
||||
CriticalSection m_cs;
|
||||
string m_refName;
|
||||
string m_counterName;
|
||||
protected:
|
||||
T m_ref;
|
||||
public:
|
||||
GlobalHandle(string sharedKey=NULL):m_cs(sharedKey)
|
||||
{
|
||||
m_refName=m_cs.getName()+"_Ref";
|
||||
m_counterName=m_cs.getName()+"_Count";
|
||||
if(!m_cs.isValid()) m_ref=HandleManager::create();
|
||||
else
|
||||
{
|
||||
m_cs.enter();
|
||||
if(!GlobalVariable::exists(m_counterName))
|
||||
{
|
||||
GlobalVariable::makeTemp(m_counterName);
|
||||
GlobalVariable::set(m_counterName,0);
|
||||
}
|
||||
if(long(GlobalVariable::get(m_counterName))==0)
|
||||
{
|
||||
m_ref=HandleManager::create();
|
||||
if(!GlobalVariable::exists(m_refName))
|
||||
{
|
||||
GlobalVariable::makeTemp(m_refName);
|
||||
GlobalVariable::set(m_refName,m_ref);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ref=(T)(GlobalVariable::get(m_refName));
|
||||
}
|
||||
GlobalVariable::set(m_counterName,GlobalVariable::get(m_counterName)+1);
|
||||
m_cs.leave();
|
||||
}
|
||||
}
|
||||
~GlobalHandle()
|
||||
{
|
||||
if(!m_cs.isValid()) {HandleManager::destroy(m_ref); return;}
|
||||
m_cs.enter();
|
||||
GlobalVariable::set(m_counterName,GlobalVariable::get(m_counterName)-1);
|
||||
if(long(GlobalVariable::get(m_counterName))==0)
|
||||
{
|
||||
HandleManager::destroy(m_ref);
|
||||
GlobalVariable::remove(m_refName);
|
||||
GlobalVariable::remove(m_counterName);
|
||||
}
|
||||
m_cs.leave();
|
||||
}
|
||||
|
||||
T ref() const {return m_ref;}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,105 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Module: Lang/Mql.mqh |
|
||||
//| This file is part of the mql4-lib project: |
|
||||
//| https://github.com/dingmaotu/mql4-lib |
|
||||
//| |
|
||||
//| Copyright 2017 Li Ding <dingmaotu@126.com> |
|
||||
//| |
|
||||
//| Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
//| you may not use this file except in compliance with the License. |
|
||||
//| You may obtain a copy of the License at |
|
||||
//| |
|
||||
//| http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
//| |
|
||||
//| Unless required by applicable law or agreed to in writing, |
|
||||
//| software distributed under the License is distributed on an |
|
||||
//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
|
||||
//| either express or implied. |
|
||||
//| See the License for the specific language governing permissions |
|
||||
//| and limitations under the License. |
|
||||
//+------------------------------------------------------------------+
|
||||
#property strict
|
||||
|
||||
#import "stdlib.ex4"
|
||||
string ErrorDescription(int error_code);
|
||||
int RGB(int red_value,int green_value,int blue_value);
|
||||
bool CompareDoubles(double number1,double number2);
|
||||
string DoubleToStrMorePrecision(double number,int precision);
|
||||
string IntegerToHexString(int integer_number);
|
||||
#import
|
||||
//+------------------------------------------------------------------+
|
||||
//| Mql language specific methods |
|
||||
//+------------------------------------------------------------------+
|
||||
class Mql
|
||||
{
|
||||
public:
|
||||
static int getLastError() {return GetLastError();}
|
||||
static string getErrorMessage(int errorCode) {return ErrorDescription(errorCode);}
|
||||
|
||||
static string doubleToString(double value,int precision) {return DoubleToStrMorePrecision(value,precision);}
|
||||
static string integerToHexString(int value) {return IntegerToHexString(value);}
|
||||
static int rgb(int red,int green,int blue) {return RGB(red,green,blue);}
|
||||
|
||||
static bool isEqual(double a,double b) {return CompareDoubles(a,b);}
|
||||
|
||||
static bool isStopped() {return IsStopped();}
|
||||
|
||||
static int getCodePage() {return MQLInfoInteger(MQL_CODEPAGE);}
|
||||
static ENUM_PROGRAM_TYPE getProgramType() {return(ENUM_PROGRAM_TYPE)MQLInfoInteger(MQL_PROGRAM_TYPE);}
|
||||
static bool isScript() {return Mql::getProgramType()==PROGRAM_SCRIPT;}
|
||||
static bool isExpert() {return Mql::getProgramType()==PROGRAM_EXPERT;}
|
||||
static bool isIndicator() {return Mql::getProgramType()==PROGRAM_INDICATOR;}
|
||||
static bool isDllAllowed() {return MQLInfoInteger(MQL_DLLS_ALLOWED)!=0;}
|
||||
static bool isTradeAllowed() {return MQLInfoInteger(MQL_TRADE_ALLOWED)!=0;}
|
||||
static bool isSignalsAllowed() {return MQLInfoInteger(MQL_SIGNALS_ALLOWED)!=0;}
|
||||
static bool isDebug() {return MQLInfoInteger(MQL_DEBUG)!=0;}
|
||||
static bool isProfiling() {return MQLInfoInteger(MQL_PROFILER)!=0;}
|
||||
static bool isTesting() {return MQLInfoInteger(MQL_TESTER)!=0;}
|
||||
static bool isOptimizing() {return MQLInfoInteger(MQL_OPTIMIZATION)!=0;}
|
||||
static bool isVisual() {return MQLInfoInteger(MQL_VISUAL_MODE)!=0;}
|
||||
static bool isFrameMode() {return MQLInfoInteger(MQL_FRAME_MODE)!=0;}
|
||||
static ENUM_LICENSE_TYPE getLicenseType() {return(ENUM_LICENSE_TYPE)MQLInfoInteger(MQL_LICENSE_TYPE);}
|
||||
static bool isFreeLicense() {return Mql::getLicenseType()==LICENSE_FREE;}
|
||||
static bool isDemoLicense() {return Mql::getLicenseType()==LICENSE_DEMO;}
|
||||
static bool isFullLicense() {return Mql::getLicenseType()==LICENSE_FULL;}
|
||||
static bool isTimeLicense() {return Mql::getLicenseType()==LICENSE_TIME;}
|
||||
|
||||
static string getProgramName() {return MQLInfoString(MQL_PROGRAM_NAME);}
|
||||
static string getProgramPath() {return MQLInfoString(MQL_PROGRAM_PATH);}
|
||||
};
|
||||
|
||||
#define ObjectAttr(Type, Private, Public) \
|
||||
public:\
|
||||
Type get##Public() const {return m_##Private;}\
|
||||
void set##Public(Type value) {m_##Private=value;}\
|
||||
private:\
|
||||
Type m_##Private\
|
||||
|
||||
#define ObjectAttrRead(Type, Private, Public) \
|
||||
public:\
|
||||
Type get##Public() const {return m_##Private;}\
|
||||
private:\
|
||||
Type m_##Private\
|
||||
|
||||
#define ObjectAttrWrite(Type, Private, Public) \
|
||||
public:\
|
||||
void set##Public(Type value) {m_##Private=value;}\
|
||||
private:\
|
||||
Type m_##Private\
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define Debug(msg) Print(">>> DEBUG: In ",__FUNCTION__,"(",__FILE__,":",__LINE__,") [", msg, "]")
|
||||
#else
|
||||
#define Debug(msg)
|
||||
#endif
|
||||
|
||||
//--- Execute some code in the global scope
|
||||
#define BEGIN_EXECUTE(Name) class __Execute##Name\
|
||||
{\
|
||||
public:__Execute##Name()\
|
||||
{
|
||||
#define END_EXECUTE(Name) \
|
||||
}\
|
||||
}\
|
||||
__execute##Name;
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,200 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Module: Lang/Native.mqh |
|
||||
//| This file is part of the mql4-lib project: |
|
||||
//| https://github.com/dingmaotu/mql4-lib |
|
||||
//| |
|
||||
//| Copyright 2016-2017 Li Ding <dingmaotu@126.com> |
|
||||
//| |
|
||||
//| Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
//| you may not use this file except in compliance with the License. |
|
||||
//| You may obtain a copy of the License at |
|
||||
//| |
|
||||
//| http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
//| |
|
||||
//| Unless required by applicable law or agreed to in writing, |
|
||||
//| software distributed under the License is distributed on an |
|
||||
//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
|
||||
//| either express or implied. |
|
||||
//| See the License for the specific language governing permissions |
|
||||
//| and limitations under the License. |
|
||||
//+------------------------------------------------------------------+
|
||||
#property strict
|
||||
|
||||
// Assume MT5 is 64bit, which is the default.
|
||||
// Even though MT5 can be 32bit, there is no way to detect this
|
||||
// by using preprocessor macros. Instead, MetaQuotes provides a
|
||||
// function called IsX64 to detect this dynamically
|
||||
|
||||
// This is just absurd. Why do you want to know the bitness of
|
||||
// the runtime? To define pointer related entities at compile time!
|
||||
// All integer types in MQL is uniform on both 32bit or 64bit
|
||||
// architectures, so it is almost useless to have a runtime function IsX64.
|
||||
|
||||
// Why not a __X64__?
|
||||
#ifdef __MQL5__
|
||||
#define __X64__
|
||||
#endif
|
||||
|
||||
#ifdef __X64__
|
||||
#define intptr_t long
|
||||
#define uintptr_t ulong
|
||||
#define size_t long
|
||||
#else
|
||||
#define intptr_t int
|
||||
#define uintptr_t uint
|
||||
#define size_t int
|
||||
#endif
|
||||
|
||||
//--- _WIN32_WINNT version constants
|
||||
#define _WIN32_WINNT_NT4 0x0400 // Windows NT 4.0
|
||||
#define _WIN32_WINNT_WIN2K 0x0500 // Windows 2000
|
||||
#define _WIN32_WINNT_WINXP 0x0501 // Windows XP
|
||||
#define _WIN32_WINNT_WS03 0x0502 // Windows Server 2003
|
||||
#define _WIN32_WINNT_WIN6 0x0600 // Windows Vista
|
||||
#define _WIN32_WINNT_VISTA 0x0600 // Windows Vista
|
||||
#define _WIN32_WINNT_WS08 0x0600 // Windows Server 2008
|
||||
#define _WIN32_WINNT_LONGHORN 0x0600 // Windows Vista
|
||||
#define _WIN32_WINNT_WIN7 0x0601 // Windows 7
|
||||
#define _WIN32_WINNT_WIN8 0x0602 // Windows 8
|
||||
#define _WIN32_WINNT_WINBLUE 0x0603 // Windows 8.1
|
||||
#define _WIN32_WINNT_WINTHRESHOLD 0x0A00 // Windows 10
|
||||
#define _WIN32_WINNT_WIN10 0x0A00 // Windows 10
|
||||
|
||||
//--- define you own for your target platform
|
||||
#define WINVER 0x0A00
|
||||
#define _WIN32_WINNT 0x0A00
|
||||
|
||||
#define FORMAT_MESSAGE_FROM_SYSTEM 0x00001000
|
||||
#define FORMAT_MESSAGE_IGNORE_INSERTS 0x00000200
|
||||
|
||||
#import "kernel32.dll"
|
||||
void RtlMoveMemory(intptr_t dest,const uchar &array[],size_t length);
|
||||
void RtlMoveMemory(uchar &array[],intptr_t src,size_t length);
|
||||
void RtlMoveMemory(intptr_t &dest,intptr_t src,size_t length);
|
||||
int lstrlen(intptr_t psz);
|
||||
int lstrlenW(intptr_t psz);
|
||||
uintptr_t lstrcpynW(string &s1,uintptr_t s2,int length);
|
||||
uintptr_t lstrcpynW(uintptr_t s1,string &s2,int length);
|
||||
|
||||
int MultiByteToWideChar(uint codePage,
|
||||
uint flags,
|
||||
const intptr_t multiByteString,
|
||||
int lengthMultiByte,
|
||||
string &str,
|
||||
int length
|
||||
);
|
||||
uint FormatMessageW(uint dwFlags,
|
||||
intptr_t lpSource,
|
||||
uint dwMessageId,
|
||||
uint dwLanguageId,
|
||||
ushort &buffer[],
|
||||
uint nSize,
|
||||
intptr_t Arguments
|
||||
);
|
||||
#import
|
||||
|
||||
//--- This is a standard header of the official MetaTrader distribution
|
||||
#include <WinUser32.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Copy the memory contents pointed by src to array |
|
||||
//| array parameter should be initialized to the desired size |
|
||||
//+------------------------------------------------------------------+
|
||||
void ArrayFromPointer(uchar &array[],intptr_t src,int count=WHOLE_ARRAY)
|
||||
{
|
||||
int size=(count==WHOLE_ARRAY)?ArraySize(array):count;
|
||||
RtlMoveMemory(array,src,(size_t)size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Copy array to the memory pointed by dest |
|
||||
//+------------------------------------------------------------------+
|
||||
void ArrayToPointer(const uchar &array[],intptr_t dest,int count=WHOLE_ARRAY)
|
||||
{
|
||||
int size=(count==WHOLE_ARRAY)?ArraySize(array):count;
|
||||
RtlMoveMemory(dest,array,(size_t)size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| For void** type, dereference a level to void* |
|
||||
//+------------------------------------------------------------------+
|
||||
intptr_t DereferencePointer(intptr_t pointer)
|
||||
{
|
||||
intptr_t res=0;
|
||||
RtlMoveMemory(res,pointer,sizeof(intptr_t));
|
||||
return res;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Read a valid wide character string to the MQL environment |
|
||||
//+------------------------------------------------------------------+
|
||||
string StringFromPointer(intptr_t psz,int len=0)
|
||||
{
|
||||
if(len < 0) return NULL;
|
||||
if(len==0) {len=lstrlenW(psz);}
|
||||
string res;
|
||||
StringInit(res,len+1);
|
||||
lstrcpynW(res,psz,len+1);
|
||||
return res;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the pointer address of a string |
|
||||
//+------------------------------------------------------------------+
|
||||
uintptr_t StringToPointer(string &s)
|
||||
{
|
||||
return lstrcpynW(s,0,0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Read a valid utf-8 string to the MQL environment |
|
||||
//| With this function, there is no need to copy the string to char |
|
||||
//| array, and convert with CharArrayToString |
|
||||
//+------------------------------------------------------------------+
|
||||
string StringFromUtf8Pointer(intptr_t psz,int len)
|
||||
{
|
||||
if(len < 0) return NULL;
|
||||
string res;
|
||||
int required=MultiByteToWideChar(CP_UTF8,0,psz,len,res,0);
|
||||
StringInit(res,required);
|
||||
int resLength = MultiByteToWideChar(CP_UTF8,0,psz,len,res,required);
|
||||
if(resLength != required)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| for null-terminated string |
|
||||
//+------------------------------------------------------------------+
|
||||
string StringFromUtf8Pointer(intptr_t psz)
|
||||
{
|
||||
if(psz==0) return NULL;
|
||||
int len=lstrlen(psz);
|
||||
if(len==0) return NULL;
|
||||
return StringFromUtf8Pointer(psz, len);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Convert a utf-8 byte array to a string |
|
||||
//+------------------------------------------------------------------+
|
||||
string StringFromUtf8(const uchar &utf8[])
|
||||
{
|
||||
return CharArrayToString(utf8, 0, -1, CP_UTF8);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Convert a string to a utf-8 byte array |
|
||||
//+------------------------------------------------------------------+
|
||||
void StringToUtf8(const string str,uchar &utf8[],bool ending=true)
|
||||
{
|
||||
if(!ending && str=="") return;
|
||||
int count=ending ? -1 : StringLen(str);
|
||||
StringToCharArray(str,utf8,0,count,CP_UTF8);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get system defined error code message |
|
||||
//+------------------------------------------------------------------+
|
||||
string GetErrorMessage(int errorCode)
|
||||
{
|
||||
static ushort buffer[64*1024];
|
||||
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
0,errorCode,0,buffer,ArraySize(buffer),0);
|
||||
return ShortArrayToString(buffer);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -1,11 +1,26 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| AtomicCounter.mqh |
|
||||
//| Copyright 2016, Li Ding |
|
||||
//| dingmaotu@hotmail.com |
|
||||
//| Module: AtomicCounter.mqh |
|
||||
//| This file is part of the mql-zmq project: |
|
||||
//| https://github.com/dingmaotu/mql-zmq |
|
||||
//| |
|
||||
//| Copyright 2016-2017 Li Ding <dingmaotu@hotmail.com> |
|
||||
//| |
|
||||
//| Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
//| you may not use this file except in compliance with the License. |
|
||||
//| You may obtain a copy of the License at |
|
||||
//| |
|
||||
//| http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
//| |
|
||||
//| Unless required by applicable law or agreed to in writing, |
|
||||
//| software distributed under the License is distributed on an |
|
||||
//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
|
||||
//| either express or implied. |
|
||||
//| See the License for the specific language governing permissions |
|
||||
//| and limitations under the License. |
|
||||
//+------------------------------------------------------------------+
|
||||
#property strict
|
||||
|
||||
#include "Common.mqh"
|
||||
#include <Mql/Lang/Native.mqh>
|
||||
|
||||
#import "libzmq.dll"
|
||||
intptr_t zmq_atomic_counter_new(void);
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common.mqh |
|
||||
//| This file is part of mql4-lib project (Lang/Native.mqh): |
|
||||
//| (github.com/dingmaotu/mql4-lib) |
|
||||
//| Copyright 2016, Li Ding |
|
||||
//| dingmaotu@hotmail.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property strict
|
||||
|
||||
#include "Errno.mqh"
|
||||
|
||||
// Assume MT5 is 64bit, which is the default.
|
||||
// Even though MT5 can be 32bit, there is no way to detect this
|
||||
// by using preprocessor macros. Instead, MetaQuotes provides a
|
||||
// function called IsX64 to detect this dynamically
|
||||
|
||||
// This is just absurd. Why do you want to know the bitness of
|
||||
// the runtime? To define pointer related entities at compile time!
|
||||
// All integer types in MQL is uniform on both 32bit or 64bit
|
||||
// architectures, so it is almost useless to have a runtime function IsX64.
|
||||
|
||||
// Why not a __X64__?
|
||||
#ifdef __MQL5__
|
||||
#define __X64__
|
||||
#endif
|
||||
|
||||
#ifdef __X64__
|
||||
#define intptr_t long
|
||||
#define uintptr_t ulong
|
||||
#define size_t long
|
||||
#else
|
||||
#define intptr_t int
|
||||
#define uintptr_t uint
|
||||
#define size_t int
|
||||
#endif
|
||||
|
||||
#import "kernel32.dll"
|
||||
void RtlMoveMemory(intptr_t dest,const uchar &array[],size_t length);
|
||||
void RtlMoveMemory(uchar &array[],intptr_t src,size_t length);
|
||||
int lstrlen(intptr_t psz);
|
||||
int MultiByteToWideChar(uint codePage,
|
||||
uint flags,
|
||||
const intptr_t multiByteString,
|
||||
int lengthMultiByte,
|
||||
string &str,
|
||||
int length
|
||||
);
|
||||
#import
|
||||
//+------------------------------------------------------------------+
|
||||
//| Copy the memory contents pointed by src to array |
|
||||
//| array parameter should be initialized to the desired size |
|
||||
//+------------------------------------------------------------------+
|
||||
void ArrayFromPointer(uchar &array[],intptr_t src,int count=WHOLE_ARRAY)
|
||||
{
|
||||
int size=(count==WHOLE_ARRAY)?ArraySize(array):count;
|
||||
RtlMoveMemory(array,src,(size_t)size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Copy array to the memory pointed by dest |
|
||||
//+------------------------------------------------------------------+
|
||||
void ArrayToPointer(const uchar &array[],intptr_t dest,int count=WHOLE_ARRAY)
|
||||
{
|
||||
int size=(count==WHOLE_ARRAY)?ArraySize(array):count;
|
||||
RtlMoveMemory(dest,array,(size_t)size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Read a valid utf-8 string to the MQL environment |
|
||||
//| With this function, there is no need to copy the string to char |
|
||||
//| array, and convert with CharArrayToString |
|
||||
//+------------------------------------------------------------------+
|
||||
string StringFromUtf8Pointer(intptr_t psz,int len)
|
||||
{
|
||||
if(len < 0) return NULL;
|
||||
string res;
|
||||
int required=MultiByteToWideChar(CP_UTF8,0,psz,len,res,0);
|
||||
StringInit(res,required);
|
||||
int resLength = MultiByteToWideChar(CP_UTF8,0,psz,len,res,required);
|
||||
if(resLength != required)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| for null-terminated string |
|
||||
//+------------------------------------------------------------------+
|
||||
string StringFromUtf8Pointer(intptr_t psz)
|
||||
{
|
||||
int len=lstrlen(psz);
|
||||
return StringFromUtf8Pointer(psz, len);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Convert a utf-8 byte array to a string |
|
||||
//+------------------------------------------------------------------+
|
||||
string StringFromUtf8(const uchar &utf8[])
|
||||
{
|
||||
return CharArrayToString(utf8, 0, -1, CP_UTF8);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Convert a string to a utf-8 byte array |
|
||||
//+------------------------------------------------------------------+
|
||||
void StringToUtf8(const string str,uchar &utf8[],bool ending=true)
|
||||
{
|
||||
if(!ending && str=="") return;
|
||||
int count=ending ? -1 : StringLen(str);
|
||||
StringToCharArray(str,utf8,0,count,CP_UTF8);
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define Debug(msg) Print(">>> DEBUG: In ",__FUNCTION__,"(",__FILE__,":",__LINE__,") [", msg, "]")
|
||||
#else
|
||||
#define Debug(msg)
|
||||
#endif
|
||||
//+------------------------------------------------------------------+
|
||||
+22
-6
@@ -1,12 +1,28 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Context.mqh |
|
||||
//| Copyright 2016, Li Ding |
|
||||
//| dingmaotu@hotmail.com |
|
||||
//| Module: Context.mqh |
|
||||
//| This file is part of the mql-zmq project: |
|
||||
//| https://github.com/dingmaotu/mql-zmq |
|
||||
//| |
|
||||
//| Copyright 2016-2017 Li Ding <dingmaotu@hotmail.com> |
|
||||
//| |
|
||||
//| Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
//| you may not use this file except in compliance with the License. |
|
||||
//| You may obtain a copy of the License at |
|
||||
//| |
|
||||
//| http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
//| |
|
||||
//| Unless required by applicable law or agreed to in writing, |
|
||||
//| software distributed under the License is distributed on an |
|
||||
//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
|
||||
//| either express or implied. |
|
||||
//| See the License for the specific language governing permissions |
|
||||
//| and limitations under the License. |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
#include "Common.mqh"
|
||||
#property strict
|
||||
#include <Mql/Lang/Mql.mqh>
|
||||
#include <Mql/Lang/Native.mqh>
|
||||
#include <Mql/Lang/GlobalVariable.mqh>
|
||||
#include "SocketOptions.mqh"
|
||||
#include "GlobalHandle.mqh"
|
||||
|
||||
//--- Context options
|
||||
#define ZMQ_IO_THREADS 1
|
||||
|
||||
+18
-1
@@ -1,5 +1,22 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Errno.mqh |
|
||||
//| Module: Errno.mqh |
|
||||
//| This file is part of the mql-zmq project: |
|
||||
//| https://github.com/dingmaotu/mql-zmq |
|
||||
//| |
|
||||
//| Copyright 2016-2017 Li Ding <dingmaotu@hotmail.com> |
|
||||
//| |
|
||||
//| Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
//| you may not use this file except in compliance with the License. |
|
||||
//| You may obtain a copy of the License at |
|
||||
//| |
|
||||
//| http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
//| |
|
||||
//| Unless required by applicable law or agreed to in writing, |
|
||||
//| software distributed under the License is distributed on an |
|
||||
//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
|
||||
//| either express or implied. |
|
||||
//| See the License for the specific language governing permissions |
|
||||
//| and limitations under the License. |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
// Following error codes come from Microsoft CRT header errno.h
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| GlobalHandle.mqh |
|
||||
//| This file is part of mql4-lib project (Lang/GlobalVariable.mqh): |
|
||||
//| (github.com/dingmaotu/mql4-lib) |
|
||||
//| Copyright 2017, Li Ding |
|
||||
//| dingmaotu@hotmail.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property strict
|
||||
//+------------------------------------------------------------------+
|
||||
//| Wraps global variable functions |
|
||||
//+------------------------------------------------------------------+
|
||||
class GlobalVariable
|
||||
{
|
||||
public:
|
||||
static int total() {return GlobalVariablesTotal();}
|
||||
static string name(int index) {return GlobalVariableName(index);}
|
||||
static void flush() {GlobalVariablesFlush();}
|
||||
|
||||
static bool exists(string name) {return GlobalVariableCheck(name);}
|
||||
static datetime lastAccess(string name) {return GlobalVariableTime(name);}
|
||||
|
||||
static bool makeTemp(string name) {return GlobalVariableTemp(name);}
|
||||
static double get(string name) {return GlobalVariableGet(name);}
|
||||
static bool get(string name,double &value) {return GlobalVariableGet(name,value);}
|
||||
static datetime set(string name,double value) {return GlobalVariableSet(name,value);}
|
||||
static bool setOn(string name,double value,double check) {return GlobalVariableSetOnCondition(name,value,check);}
|
||||
|
||||
static bool remove(string name) {return GlobalVariableDel(name);}
|
||||
static bool removeAll(string prefix=NULL,datetime before=0) {return GlobalVariablesDeleteAll(prefix,before);}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| CriticalSection object for making atomic operations |
|
||||
//| |
|
||||
//| An exmaple of creating a global context (the creation and destroy|
|
||||
//| are both enclosed between the SAME critical section): |
|
||||
//| |
|
||||
//| enter() |
|
||||
//| if(refcount==0) create context |
|
||||
//| else refcontext |
|
||||
//| increase refcount |
|
||||
//| leave() |
|
||||
//| |
|
||||
//| enter() |
|
||||
//| decrease refcount |
|
||||
//| if(refcount==0) context destroy |
|
||||
//| leave() |
|
||||
//+------------------------------------------------------------------+
|
||||
class CriticalSection
|
||||
{
|
||||
private:
|
||||
const string m_name;
|
||||
public:
|
||||
CriticalSection(string name):m_name(name){}
|
||||
|
||||
bool isValid() const {return m_name!=NULL;}
|
||||
string getName() const {return m_name;}
|
||||
|
||||
void enter() { while(!GlobalVariable::makeTemp(m_name) && !IsStopped())Sleep(100); }
|
||||
bool tryEnter() { return GlobalVariable::makeTemp(m_name); }
|
||||
void leave() { GlobalVariable::remove(m_name);}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| A reference counted global pointer (or handle) |
|
||||
//| HandleManager should implement 2 static methods: create & destroy|
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename T,typename HandleManager>
|
||||
class GlobalHandle
|
||||
{
|
||||
private:
|
||||
CriticalSection m_cs;
|
||||
string m_refName;
|
||||
string m_counterName;
|
||||
protected:
|
||||
T m_ref;
|
||||
public:
|
||||
GlobalHandle(string sharedKey=NULL):m_cs(sharedKey)
|
||||
{
|
||||
m_refName=m_cs.getName()+"_Ref";
|
||||
m_counterName=m_cs.getName()+"_Count";
|
||||
if(!m_cs.isValid()) m_ref=HandleManager::create();
|
||||
else
|
||||
{
|
||||
m_cs.enter();
|
||||
if(!GlobalVariable::exists(m_counterName))
|
||||
{
|
||||
GlobalVariable::makeTemp(m_counterName);
|
||||
GlobalVariable::set(m_counterName,0);
|
||||
}
|
||||
if(long(GlobalVariable::get(m_counterName))==0)
|
||||
{
|
||||
m_ref=HandleManager::create();
|
||||
if(!GlobalVariable::exists(m_refName))
|
||||
{
|
||||
GlobalVariable::makeTemp(m_refName);
|
||||
GlobalVariable::set(m_refName,m_ref);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ref=(T)(GlobalVariable::get(m_refName));
|
||||
}
|
||||
GlobalVariable::set(m_counterName,GlobalVariable::get(m_counterName)+1);
|
||||
m_cs.leave();
|
||||
}
|
||||
}
|
||||
~GlobalHandle()
|
||||
{
|
||||
if(!m_cs.isValid()) {HandleManager::destroy(m_ref); return;}
|
||||
m_cs.enter();
|
||||
GlobalVariable::set(m_counterName,GlobalVariable::get(m_counterName)-1);
|
||||
if(long(GlobalVariable::get(m_counterName))==0)
|
||||
{
|
||||
HandleManager::destroy(m_ref);
|
||||
GlobalVariable::remove(m_refName);
|
||||
GlobalVariable::remove(m_counterName);
|
||||
}
|
||||
m_cs.leave();
|
||||
}
|
||||
|
||||
T ref() const {return m_ref;}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
+20
-4
@@ -1,11 +1,27 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Socket.mqh |
|
||||
//| Copyright 2016, Li Ding |
|
||||
//| dingmaotu@hotmail.com |
|
||||
//| Module: Socket.mqh |
|
||||
//| This file is part of the mql-zmq project: |
|
||||
//| https://github.com/dingmaotu/mql-zmq |
|
||||
//| |
|
||||
//| Copyright 2016-2017 Li Ding <dingmaotu@hotmail.com> |
|
||||
//| |
|
||||
//| Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
//| you may not use this file except in compliance with the License. |
|
||||
//| You may obtain a copy of the License at |
|
||||
//| |
|
||||
//| http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
//| |
|
||||
//| Unless required by applicable law or agreed to in writing, |
|
||||
//| software distributed under the License is distributed on an |
|
||||
//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
|
||||
//| either express or implied. |
|
||||
//| See the License for the specific language governing permissions |
|
||||
//| and limitations under the License. |
|
||||
//+------------------------------------------------------------------+
|
||||
#property strict
|
||||
|
||||
#include "Common.mqh"
|
||||
#include <Mql/Lang/Mql.mqh>
|
||||
#include <Mql/Lang/Native.mqh>
|
||||
#include "Context.mqh"
|
||||
#include "SocketOptions.mqh"
|
||||
#include "ZmqMsg.mqh"
|
||||
|
||||
@@ -1,13 +1,26 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Socket.mqh |
|
||||
//| Copyright 2016, Li Ding |
|
||||
//| dingmaotu@hotmail.com |
|
||||
//| Module: SocketOptions.mqh |
|
||||
//| This file is part of the mql-zmq project: |
|
||||
//| https://github.com/dingmaotu/mql-zmq |
|
||||
//| |
|
||||
//| Copyright 2016-2017 Li Ding <dingmaotu@hotmail.com> |
|
||||
//| |
|
||||
//| Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
//| you may not use this file except in compliance with the License. |
|
||||
//| You may obtain a copy of the License at |
|
||||
//| |
|
||||
//| http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
//| |
|
||||
//| Unless required by applicable law or agreed to in writing, |
|
||||
//| software distributed under the License is distributed on an |
|
||||
//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
|
||||
//| either express or implied. |
|
||||
//| See the License for the specific language governing permissions |
|
||||
//| and limitations under the License. |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2016, Li Ding"
|
||||
#property link "dingmaotu@hotmail.com"
|
||||
#property strict
|
||||
|
||||
#include "Common.mqh"
|
||||
#include <Mql/Lang/Native.mqh>
|
||||
|
||||
#import "libzmq.dll"
|
||||
// We can overload the same function for different data types
|
||||
|
||||
+19
-6
@@ -1,13 +1,26 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Z85.mqh |
|
||||
//| Copyright 2016, Li Ding |
|
||||
//| dingmaotu@hotmail.com |
|
||||
//| Module: Z85.mqh |
|
||||
//| This file is part of the mql-zmq project: |
|
||||
//| https://github.com/dingmaotu/mql-zmq |
|
||||
//| |
|
||||
//| Copyright 2016-2017 Li Ding <dingmaotu@hotmail.com> |
|
||||
//| |
|
||||
//| Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
//| you may not use this file except in compliance with the License. |
|
||||
//| You may obtain a copy of the License at |
|
||||
//| |
|
||||
//| http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
//| |
|
||||
//| Unless required by applicable law or agreed to in writing, |
|
||||
//| software distributed under the License is distributed on an |
|
||||
//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
|
||||
//| either express or implied. |
|
||||
//| See the License for the specific language governing permissions |
|
||||
//| and limitations under the License. |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2016, Li Ding"
|
||||
#property link "dingmaotu@hotmail.com"
|
||||
#property strict
|
||||
|
||||
#include "Common.mqh"
|
||||
#include <Mql/Lang/Native.mqh>
|
||||
|
||||
#import "libzmq.dll"
|
||||
// Encode data with Z85 encoding. Returns 0(NULL) if failed
|
||||
|
||||
Binary file not shown.
+22
-7
@@ -1,12 +1,26 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ZmqMsg.mqh |
|
||||
//| Copyright 2016, Li Ding |
|
||||
//| dingmaotu@hotmail.com |
|
||||
//| Module: ZmqMsg.mqh |
|
||||
//| This file is part of the mql-zmq project: |
|
||||
//| https://github.com/dingmaotu/mql-zmq |
|
||||
//| |
|
||||
//| Copyright 2016-2017 Li Ding <dingmaotu@hotmail.com> |
|
||||
//| |
|
||||
//| Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||
//| you may not use this file except in compliance with the License. |
|
||||
//| You may obtain a copy of the License at |
|
||||
//| |
|
||||
//| http://www.apache.org/licenses/LICENSE-2.0 |
|
||||
//| |
|
||||
//| Unless required by applicable law or agreed to in writing, |
|
||||
//| software distributed under the License is distributed on an |
|
||||
//| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
|
||||
//| either express or implied. |
|
||||
//| See the License for the specific language governing permissions |
|
||||
//| and limitations under the License. |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2016, Li Ding"
|
||||
#property link "dingmaotu@hotmail.com"
|
||||
#property strict
|
||||
#include "Common.mqh"
|
||||
#include <Mql/Lang/Mql.mqh>
|
||||
#include <Mql/Lang/Native.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| 0MQ Message struct |
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -121,7 +135,8 @@ string ZmqMsg::getData()
|
||||
void ZmqMsg::setData(const uchar &data[])
|
||||
{
|
||||
intptr_t dest=data();
|
||||
ArrayToPointer(data,dest);
|
||||
size_t size=size();
|
||||
ArrayToPointer(data,dest,size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Wraps zmq_msg_gets: get metadata associated with the msg |
|
||||
|
||||
Reference in New Issue
Block a user