DllCall()Executes a function located in a dynamically loaded external library. Syntax
DllCall( <cDllFile>|<nDllHandle>, ;
[<nCallingConvention>] , ;
<cFuncName>|<nOrdinal> , ;
[<xParams,...>] ) --> nResult
Arguments<cDllFile> A character string holding the name of the DLL file where the function is located. This is an external DLL, not created by xHarbour. If a character string is passed for <cDllFile>, it must contain complete path information, unless the file is located in the current directory, or in the list of directories held in the SET PATH environment variable of the operating system.
<nDllHandle> Alternatively, the first parameter can be a numeric DLL handle as returned by function LoadLibrary().
<nCallingConvention> The calling convention to use for the DLL function can optionally be specified. Constants are available for this parameter. Calling conventions Constant Value Description
DC_CALL_CDECL 0x0010 C calling convention (__cdecl)
DC_CALL_STD *) 0x0020 Standard convention for WinAPI (__stdcall)
*) default
<cFuncName> This is a character string holding the symbolic name of the function to call. Unlike regular xHarbour functions, this function name is case sensitive.
<nOrdinal>
Instead of the symbolic function name, the numeric ordinal position of the function inside the DLL file can be passed. This is, however, not recommended, since ordinal positions of functions may change between DLL versions.
<xParams,...> The values of all following parameters specified in a comma separated list are passed on to the DLL function. Return
The function returns the result of the called DLL function as a numeric value.
DescriptionFunction
DllCall() can be used to execute functions located in DLL files which are not created by the xHarbour compiler and linker. This allows for executing functions residing in system DLLs of the operating system or Third Party producers, for example.
The DLL that contains a function is either specified by its numeric DLL handle, or by its symbolic file name. In the latter case,
DllCall() loads the library, executes the function and frees the library when the function has returned. When a numeric DLL handle is specified, the DLL is already loaded by LoadLibrary(), and it remains loaded when the DLL function is complete. The DLL must then be released explicitely with FreeLibrary().
When more than three parameters are specified, all <xParams,...> are passed on to the DLL function. However, since xHarbour has its own data types and more of them are available than in the C language, only values of a restricted number of data types can be passed. The values are converted to corresponding C data types.
Data type conversion PRG level C level
Character *char
C structure *void
Date DWORD
Logical DWORD
NIL ( DWORD ) NULL
Numeric
- Integer DWORD
- Decimal number double
Pointer *void
If other xHarbour data types are passed to
DllCall(), a runtime error is generated.
Note: many Windows API functions are available as a Unicode and an Ansi version. If this is the case,
DllCall() uses the Ansi version of the WinAPI function.
Example
- Code: Select all Expand view
// The example outlines how a Windows API function can be wrapped
// within an xHarbour function without reverting to xHarbour's
// extend API. The GetVolumeInformation() wrapper obtains only
// the volume name and serial number. Other information available
// from the WinAPI function is ignored. Note that the "out"
// parameters of the API must be passed by reference to DllCall().
#define DC_CALL_STD 0x0020
#define MAX_PATH 260
PROCEDURE Main
LOCAL cDrive := "D:\"
LOCAL cVolName, cVolSerial
cVolName := GetVolumeInformation( cDrive, @cVolSerial )
? cVolName // result: BACKUP
? cVolSerial // result: 584C:2AE1
RETURN
FUNCTION GetVolumeInformation( cVolume, cSerial )
LOCAL cVolumeName := Replicate( Chr(0), MAX_PATH+1 )
LOCAL nNameSize := Len( cVolumeName )
LOCAL nResult
cSerial := U2Bin(0)
nResult := ; // * C prototype *
DllCall( ;
"Kernel32.dll" , ; // DLL to call
DC_CALL_STD , ; // calling vonvention
"GetVolumeInformation" , ; // BOOL GetVolumeInformation(
cVolume , ; // LPCTSTR lpRootPathName ,
@cVolumeName , ; // LPTSTR lpVolumeNameBuffer ,
nNameSize , ; // DWORD nVolumeNameSize ,
@cSerial , ; // LPDWORD lpVolumeSerialNumber ,
0 , ; // LPDWORD lpMaximumComponentLength ,
0 , ; // LPDWORD lpFileSystemFlags ,
0 , ; // LPTSTR lpFileSystemNameBuffer ,
0 ) // DWORD nFileSystemNameSize )
// format serial number as FFFF:FFFF
cSerial := NumToHex( Bin2U(cSerial), 8 )
cSerial := Stuff( cSerial, 5, 0, ":" )
RETURN Left( cVolumeName, At( Chr(0), cVolumeName ) - 1 )