Convert an array of bytes into a ulong - mql4

How can I convert
uchar bytes[8];
to a ulong?
I can't figure this out.
I mean apart from writing a function to do it myself.

Related

Delphi: add constant to TFileTime

I am new in Delphi and I need in my project add some constant to TFileTime which is record of lower and upper part of 64bit value. How to do this in Delphi? I have found only code in C++, but i dont know how make in Delphi unsigned int64 (ULONGLONG) and also I dont know how to cast this to longword (DWORD):
ULONGLONG qwResult;
// Copy the time into a quadword.
qwResult = (((ULONGLONG) ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
// Add constant
qwResult += constant;
// Copy the result back into the FILETIME structure.
ft.dwLowDateTime = (DWORD) (qwResult & 0xFFFFFFFF );
ft.dwHighDateTime = (DWORD) (qwResult >> 32 );
Thanks
The FILETIME struct is defined as:
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME;
So, because Windows runs on little Endian, the layout of this struct is compatible with a 64 bit integer value.
So, you can cast TFileTime to UInt64, do the arithmetic, and cast back. Like this:
function IncrementedFileTime(const Value: TFileTime; const Incr: UInt64): TFileTime;
begin
Result := TFileTime(UInt64(Value) + Incr);
end;
Now, the documentation for the FILETIME record says:
It is not recommended that you add and subtract values from the
FILETIME structure to obtain relative times. Instead, you should copy
the low- and high-order parts of the file time to a ULARGE_INTEGER
structure, perform 64-bit arithmetic on the QuadPart member, and copy
the LowPart and HighPart members into the FILETIME structure.
Do not cast a pointer to a FILETIME structure to either a
ULARGE_INTEGER* or __int64* value because it can cause alignment
faults on 64-bit Windows.
This is an issue on targets where alignment errors result in hard faults. For instance Itanium. However, on x86 and x64 the code in my answer is fine because those architectures do not issue hard faults for alignment errors. Which is just as well because the Delphi compiler isn't very good at alignment.

Why i get NAN value when storing mmioRead result in double?

Why i get NAN value when trying to read .wav file and directly store it sample data in double? Before thinking about using this i was store the sample data in smallint and then convert it to double by dividing it with 32768.0 (there is no NAN value) but later on i got accuracy problem with rounding off when converting it back to wav file.
SetLength(buf, ckiData.cksize);
mmioRead(HMMIO, PAnsiChar(buf), ckiData.cksize);
Where buf are array of double. Weren't it allowed to directly storing it into array of double?
If the raw sample data really is 64-bit doubles (what audio format are you using that does that?), then yes, you can directly read into an array of doubles, eg:
var
buf: array of Double;
SetLength(buf, ckiData.cksize div SizeOf(Double));
mmioRead(HMMIO, PAnsiChar(buf), Length(buf) * SizeOf(Double));
However, most audio formats do not use doubles, so you have to first read into a suitable buffer using the correct data type (Smallint for 16-bit PCM, for example), then convert the samples afterwards.

Copying zero-terminated raw buffer of bytes to String

Sorry for all these questions I keep asking.Anyways my question is
am I properly converting the value to a string?(Not an unincode string).
const
address:dword=$0057B568;
var
a:string;
len,i:dword;
begin
len:=0;
repeat
inc(len);
until ((pbyte(address+len)^=0));//and(pbyte(address+1)^=0));(for unincode)
for I:=0 to len do
a:=a+chr(pbyte(address+I)^);
//stringreplace(a,#0,'',[rfreplaceall,rfignorecase]);
MessageBox(0,pchar(a),'',0);
end.
No, it's not correct. The code is off by one byte. First, it assumes the string is at least one character long by ignoring the first byte. Next, it copies one extra byte. Your code can be greatly simplified:
a := PAnsiChar(address);

void method (void *pixels); to delphi declaration

How should such declaration be converted to delphi?
void method (void *pixels);
And I have also the information that I should pre-allocate that variable.
could someone give me a hint?
If you need to stick to the original declaration format (as for example when converting C DLL headers), and the conversion would be:
procedure method(pixels: Pointer);
You can find dome more information on converting C headers to Delphi here
On the other hand, if you are converting the whole method or class you might want to adapt it to a more Delphi-like code. I do not know what "pixels" is, so I can hardly guess which would be the best option.
On a wild guess, if it is a matrix with some information about each pixel (position, color, alpha channel?) you can easily handle such a structure like that with object lists or create your own class to handle it.
HTH
Assuming that pixels points to an array of pixels, you could do:
procedure method(var pixels); cdecl;
If you passed pixels as untyped parameter, it is implicitly passed as pointer, which is what the C declaration does too, so the conversion matches the original perfectly. Using an untyped pointer enables you to cast it to anything you like or take its address to get the pointer. As long as you know the structure of pixels, that may be more convenient:
Let's assume pixels is a fixed size array of byte, where each bit is a pixel:
type
TPixels = array[0..7] of Byte;
const
Grey: TPixels = ($55, $AA, $55, $AA, $55, $AA, $55, $AA);
procedure method(var pixels); cdecl;
begin
Move(Grey, pixels, Sizeof(Grey));
// ...
TPixels(pixels)[3] := $FF;
// ...

Translating Vista WinAPI C++ header for Delphi - any suggestions?

I'm needing to call a Windows API function introduced in Vista from my Delphi app, but I don't have any Delphi headers which describe the function.
Related functions are already documented in the JEDI Windows API library, but not this function.
My C++ is almost non-existent, and I'm struggling to work out the Delphi definitions that correspond to the function and it's parameter as documented on MSDN.
From http://msdn.microsoft.com/en-us/library/aa814417.aspx
NETIOAPI_API GetIpInterfaceEntry(__inout PMIB_IPINTERFACE_ROW Row);
typedef struct _MIB_IPINTERFACE_ROW {
ADDRESS_FAMILY Family;
NET_LUID InterfaceLuid;
NET_IFINDEX InterfaceIndex;
ULONG MaxReassemblySize;
ULONG64 InterfaceIdentifier;
ULONG MinRouterAdvertisementInterval;
ULONG MaxRouterAdvertisementInterval;
BOOLEAN AdvertisingEnabled;
BOOLEAN ForwardingEnabled;
BOOLEAN WeakHostSend;
BOOLEAN WeakHostReceive;
BOOLEAN UseAutomaticMetric;
BOOLEAN UseNeighborUnreachabilityDetection;
BOOLEAN ManagedAddressConfigurationSupported;
BOOLEAN OtherStatefulConfigurationSupported;
BOOLEAN AdvertiseDefaultRoute;
NL_ROUTER_DISCOVERY_BEHAVIOR RouterDiscoveryBehavior;
ULONG DadTransmits;
ULONG BaseReachableTime;
ULONG RetransmitTime;
ULONG PathMtuDiscoveryTimeout;
NL_LINK_LOCAL_ADDRESS_BEHAVIOR LinkLocalAddressBehavior;
ULONG LinkLocalAddressTimeout;
ULONG ZoneIndices[ScopeLevelCount];
ULONG SitePrefixLength;
ULONG Metric;
ULONG NlMtu;
BOOLEAN Connected;
BOOLEAN SupportsWakeUpPatterns;
BOOLEAN SupportsNeighborDiscovery;
BOOLEAN SupportsRouterDiscovery;
ULONG ReachableTime;
NL_INTERFACE_OFFLOAD_ROD TransmitOffload;
NL_INTERFACE_OFFLOAD_ROD ReceiveOffload;
BOOLEAN DisableDefaultRoutes;
}MIB_IPINTERFACE_ROW, *PMIB_IPINTERFACE_ROW;
Among other bits, the bit I'm struggling with at the minute is the ZoneIndices[ScopeLevelCount] field; I can't work out what size the array is supposed to be.
This is what I've defined so far, although I haven't worked out the enums in the original C++ definition yet. I'll be explicitly loading the Windows DLL on Vista and getting the address of the new function to call.
type
PMIB_IPINTERFACE_ROW = ^MIB_IPINTERFACE_ROW;
{$EXTERNALSYM PMIB_IPINTERFACE_ROW}
_MIB_IPINTERFACE_ROW = record
Family: ADDRESS_FAMILY;
InterfaceLuid: NET_LUID;
InterfaceIndex: NET_IFINDEX;
MaxReassemblySize,
InterfaceIdentifier,
MinRouterAdvertisementInterval,
MaxRouterAdvertisementInterval: Cardinal;
AdvertisingEnabled,
ForwardingEnabled,
WeakHostSend,
WeakHostReceive,
UseAutomaticMetric,
UseNeighborUnreachabilityDetection,
ManagedAddressConfigurationSupported,
OtherStatefulConfigurationSupported,
AdvertiseDefaultRoute: LongBool;
RouterDiscoveryBehavior: NL_ROUTER_DISCOVERY_BEHAVIOR;
DadTransmits,
BaseReachableTime,
RetransmitTime,
PathMtuDiscoveryTimeout: Cardinal;
LinkLocalAddressBehavior: NL_LINK_LOCAL_ADDRESS_BEHAVIOR;
LinkLocalAddressTimeout,
ZoneIndices[ScopeLevelCount],
SitePrefixLength,
Metric,
NlMtu: Cardinal;
Connected,
SupportsWakeUpPatterns,
SupportsNeighborDiscovery,
SupportsRouterDiscovery: LongBool;
ReachableTime: Cardinal;
TransmitOffload: NL_INTERFACE_OFFLOAD_ROD;
ReceiveOffload: NL_INTERFACE_OFFLOAD_ROD;
DisableDefaultRoutes: LongBool;
end;
{$EXTERNALSYM _MIB_IPINTERFACE_ROW}
MIB_IPINTERFACE_ROW = _MIB_IPINTERFACE_ROW;
{$EXTERNALSYM MIB_IPINTERFACE_ROW}
TMibIpInterfaceRow = MIB_IPINTERFACE_ROW;
PMibIpInterfaceRow = PMIB_IPINTERFACE_ROW;
const
iphlpapilib = 'iphlpapi.dll';
var
HIpHlpApi: THandle = 0;
GetIpInterfaceEntry: function(const pArpEntry: MIB_IPINTERFACE_ROW): LongInt; stdcall;
{$EXTERNALSYM GetIpInterfaceEntry}
Does anybody out there have suggestions or tips/tricks for translating a function definition like this?
Many thanks,
Conor
The Win32 BOOLEAN type is one byte, but Delphi's LongBool type is four. Use Delphi's ByteBool instead.
Maybe you can try "C 2 pas"
http://cc.embarcadero.com/Item/26951
Also found these tools:
http://www.drbob42.com/delphi/headconv.htm
http://rvelthuis.de/programs/convertpack.html
http://rvelthuis.de/articles/articles-convert.html#cconvs
Hmm. A strange structore. But if you look into w2def.h, you can see that ScopeLevelCount=16. So your array should have 16 elements,
Make sure you use the packed command when defining your record because Delphi aligns complex data types on 2, 4 or 8 byte boundaries by default.
TExample = record
f1: Integer; // start at offset 0x00
f2: Char; // start at offset 0x04
f3: Integer; // start at offset 0x06 or 0x08 depending on alignment
end;
TExample = packed record // this is what c++ would do
f1: Integer; // start at offset 0x00
f2: Char; // start at offset 0x04
f3: Integer; // start at offset 0x05
end;
The ZoneIndices array should be defined like this:
ZoneIndices : array [0..ScopeLevelCount - 1] of Cardinal;
ScopeLevelCount is a constant that is 16
I often used Dr. Bob's Header Converter for this task, but mostly I took the long and tedious way of manually performing the conversion, because it helped me to understand the API better. (Because I was going to use it and I have to familiarize myself with it anyway)
Also see this article: http://www.delphi-jedi.org/api-howto.html
In general it's best not to put to much hopes on a header conversion tool, because C++ is a very powerful and complex language. Most conversion tools I tested only supported a subset of C++ and its preprocessor, thus making it necessary to manually make fixes to the generated source.
you can investigate some already translated APIs/structures that related to this subject and convert it yourself. for example this one
I don't see any field of type ULONG64 in the translation, but I do in the original.
Further, FPC also has an header converter which works fine for structs. Typically windows api structures are packed.
In doubt, use some free msvc product to write the sizeof(structure) and do the same under pascal. If that matches, and you still have doubts, calculate field offsets with a bit of pointer magic and compare them.

Resources