Looking Windows.pas in Delphi, I see that there are several signatures as LoadLibrary (A) or (W)
for loading a specific module. What are the differences between
The Windows API provides either ANSI strings (A
) or Unicode strings (W
). Interally, the Windows API has both available. However, Delphi is defaulted to either one or the other, depending on the version of Delphi. Many other Windows languages do this too. The language uses either ANSI or Unicode strings as a default.
In Delphi versions prior to 2009, the ANSI API calls were used, suffixed with an A
. That was when Delphi primarily used ANSI strings. As of Delphi 2009 and above, Unicode has been enforced. That also made the default API calls to Unicode, suffixed with a W
. Unicode has always been supported in Delphi, but as of 2009 it's been enforced as the default, favored over ANSI. In those older versions, functions such as LoadLibrary
mapped to the ANSI version LoadLibraryA
.
The particular API call you're referring to LoadLibrary
is available as either LoadLibraryA
or LoadLibraryW
. Windows.h
also provides a generic LoadLibrary
function, which internally uses the preferred Unicode version. The A
and W
difference provides developers the option for backwards compatibility, as with many of Microsoft's products. If the language is primarily ANSI Strings, you can explicitly use Unicode. Or, if the language is primarily Unicode, you can explicitly use ANSI.
Long story short, at one point Windows itself made the switch from ANSI strings to Unicode strings as default. However still provided backwards compatibility. Later Delphi versions have been changed to use whatever the preferred defaults are - in this case they're Unicode.
To summarize:
You can learn more about Microsoft's introduction of Unicode here as well as here.
why there is in Delphi XE2 LoadLibrary and LoadLibraryW when they are the same api in Windows?
For compatibility with the Win32 API and various tutorials/examples, and for compatibility with Ansi and Unicode versions of Delphi.
The Win32 API defines only LoadLibraryA()
(Ansi) and LoadLibraryW()
(Unicode) as actual functions (exported from kernel32.dll). LoadLibrary()
is not a function at all, it is a preprocessor macro (defined in winbase.h
) that maps to either LoadLibraryA()
or LoadLibraryW()
, based on whether the project is configured to compile for an Ansi or Unicode environment:
#ifdef UNICODE
#define LoadLibrary LoadLibraryW
#else
#define LoadLibrary LoadLibraryA
#endif
When a C/C++ app uses a TCHAR
-based string to call the generic LoadLibrary()
"function", it can be compiled and linked for either environment by simply changing the project settings rather than changing the source code, eg:
HMODULE hLib = LoadLibrary(TEXT("filename"));
// calls either LoadLibraryA("filename") or LoadLibraryW(L"filename")
// depending on whether UNICODE is defined while compiling...
Delphi, on the other hand, does not support .h
files, and thus cannot utilize all of Microsoft's existing function declarations. All library functions and data types have to be re-declared in Pascal (hence the existence of the Windows
unit and other related units for the Win32 API).
In the case of LoadLibrary()
, all versions of Delphi declare LoadLibraryA()
and LoadLibraryW()
as real functions imported from kernel32.dll
, using PAnsiChar
and PWideChar
parameters, respectively:
function LoadLibraryA(const lpFileName: PAnsiChar): HMODULE; stdcall; external kernel32 name 'LoadLibraryA';
function LoadLibraryW(const lpFileName: PWideChar): HMODULE; stdcall; external kernel32 name 'LoadLibraryW';
Delphi does not support preprocessor macros, so it declares LoadLibrary()
as a function that imports whichever DLL function matches Delphi's generic PChar
type. So, in Delphi 2007 and earlier where PChar
is PAnsiChar
, LoadLibrary()
is declared to import LoadLibraryA()
, and in Delphi 2009 and later where PChar
is PWideChar
, LoadLibrary()
is declared to import LoadLibraryW()
instead:
// Delphi 2007 and earlier...
function LoadLibrary(const lpFileName: PChar): HMODULE; stdcall; external kernel32 name 'LoadLibraryA';
// Delphi 2009 and later...
function LoadLibrary(const lpFileName: PChar): HMODULE; stdcall; external kernel32 name 'LoadLibraryW';
When a Delphi app uses a PChar
to call the generic LoadLibrary()
, it can be compiled in multiple versions of Delphi without having to change source code:
hLib := LoadLibrary(PChar(filename));
// calls either LoadLibraryA(PAnsiChar(filename) or LoadLibraryW(PWideChar(filename))
// depending on whether Delphi natively uses Ansi or Unicode strings...
These factors apply to any TCHAR
-based API, not just to LoadLibrary()
specifically. When a given Win32 API supports A
and W
versions, MSDN documents it in terms of its generic TCHAR
version. Remember that the Win32 API predates Unicode, and TCHAR
was Microsoft's solution to migrate developers from Ansi APIs to Unicode APIs when they were first introduced in Windows NT, while still allowing developers to support earlier Windows versions. For backwards compatibility with legacy apps, those existing Ansi APIs are still supported in modern Windows versions, albeit deprecated in favor of the Unicode APIs. New APIs introduced tend to be Unicode-only moving forward.