//+------------------------------------------------------------------+ //| Module: Lang/Native.mqh | //| This file is part of the mql4-lib project: | //| https://github.com/dingmaotu/mql4-lib | //| | //| Copyright 2016-2017 Li Ding | //| | //| 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 #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 ); #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); } //+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+