API callback |
Top Previous Next |
PInvoke > API callback API function may use callback parameters. In this case not only the parameters of the API function have to be adapted, the parameters of the callback function have to be adapted too. The "EnumSystemLocales" function is such an example:
type TFNLocaleEnumProc = Pointer;
{$EXTERNALSYM EnumSystemLocales} function EnumSystemLocales(lpLocaleEnumProc: TFNLocaleEnumProc; dwFlags: DWORD): bool; stdcall;
implementation
function EnumSystemLocales; external kernel32 name 'EnumSystemLocales';
function EnumLocalesCallback(LocaleID: PChar): Integer; stdcall; begin // ... end;
procedure CallEnum; begin EnumSystemLocales(@EnumLocalesCallback, LCID_SUPPORTED); end;
The callback function "EnumLocalesCallback" has a PChar parameter, which becomes the simulated PChar-class in C#. Of course the unmanaged code couldn't do anything with it. Delphi2C# therefore creates a sibling function to "EnumLocalesCallback" with the same name, but with parameters, which are conform with unmanaged code and which can be used to call the original "EnumLocalesCallback" function. By means of the function "Marshall.GetFunctionPointerForDelegate<TDelegate>", the "EnumLocalesCallback" sibling can be converted than to a function pointer, that can be called in the unmanaged code.
This is what Delphi2C# makes from the code above:
public delegate int callback__0([MarshalAs(UnmanagedType.LPStr)] string LocaleID); // LPWStr manually corrected here public static int EnumLocalesCallback([MarshalAs(UnmanagedType.LPStr)] string LocaleID) // LPWStr manually corrected here { return EnumLocalesCallback(new PChar(LocaleID)); }
[DllImport(kernel32, SetLastError=true)] public static extern bool /*stdcall*/ EnumSystemLocales( IntPtr lpLocaleEnumProc, DWORD dwFlags);
public static int /*stdcall*/ EnumLocalesCallback(PChar LocaleID) { int result = 0; // ... return result; }
public static void CallEnum() { EnumSystemLocales(Marshal.GetFunctionPointerForDelegate<callback__0>(EnumLocalesCallback), LCID_SUPPORTED); }
As template parameter "TDelegate" for "GetFunctionPointerForDelegate<TDelegate>" the delegate "callback__0" is used. "callback__0" just has the signature of the "EnumLocalesCallback" sibling.
When "EnumSystemLocales" is called in the managed code, the unmanaged code will call the "EnumLocalesCallback" sibling, which then will call the original "EnumLocalesCallback".
|
This page belongs to the Delphi2C# Documentation |
Delphi2C# home Content |