What's the difference between these Windows API signatures in Delphi?

穿精又带淫゛_ 提交于 2020-06-12 05:06:01

问题


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 them and could I trust to call LoadLibrary always for all types of Windows platforms?


回答1:


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:

  • LoadLibraryA - Loads library via ANSI strings
  • LoadLibraryW - Loads library via Unicode strings
  • LoadLibrary - Loads library using preferred default (Unicode Strings)
  • Ancient versions of Windows used only ANSI strings before introducing Unicode
  • Windows provided backwards compatibility by defaulting to ANSI versions - but eventually switched defaults to Unicode (not sure at which version)

You can learn more about Microsoft's introduction of Unicode here as well as here.




回答2:


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.



来源:https://stackoverflow.com/questions/30699776/whats-the-difference-between-these-windows-api-signatures-in-delphi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!