{ A Unit to import functions from the
   'm' (Linix) or 'msvcrt.dll' (Windows) dynamic link library.

  License: modified LGPL with linking exception (like RTL, FCL and LCL)

  See the file COPYING.modifiedLGPL.txt, included in the Lazarus distribution,
  for details about the license.


  This Unit could be easily extended to load more functions from the DLL.
  There are several points where the functions has to be added.
  Use the "nextafter" function as an guide how to add.

  Version Date        Change
  0.0.1   2024-09-07  First release, only the function nextafter is loaded
}

unit umsvcrtdll;

{$mode ObjFPC}{$H+}

interface

uses
  Classes, SysUtils, ctypes;

{ Conditional compiling "DynamicLink"
   defined: the unit will load the DLL on startup and assign all functions,
            if *all* functions available the variable "DllAvailable" becomes true.
   undefined : implicit linking, the application failes if the DLL is not available.
            The variable DllAvailable is always true
}
{$DEFINE DynamicLink}

const
  DLLNAME = {$ifdef linux} 'm' {$else} 'msvcrt.dll' {$endif};

var
  {DllAvailable a global variable to check if all functions from the DLL are loaded
    if false, still some of the function could be loaded or available due to coded
    alternatives }
  DllAvailable : Boolean = False;

{$IFDEF DynamicLink}
var
  nextafter : function(x, y: cdouble): cdouble; cdecl = Nil;
  // Add a new function here (0)
{$ELSE}
function nextafter(x, y: cdouble): cdouble; cdecl; external DLLName {$ifndef linux} Name '_nextafter' {$endif};
// and add new function here (1)
{$ENDIF}


implementation
var
  HDll : THandle; // Handle to the DLL

function InitDll : Boolean;
begin
{$IFDEF DynamicLink}
  Result := False;
  HDll := LoadLibrary(DLLNAME);
  if HDll >= 32 then { success }
  begin
    Pointer(nextafter) := GetProcAddress(HDll, '_nextafter');
    // and add new function here (3)

    Result := True;
    Result := Result and Assigned(nextafter);
    // and add new function here (4)
  end;
  // Here you may add assignments for replacement functions, found in the source
  // Example: if not Assigned(nextafter) then nextafter := @MySpecialImplementationOfNextAfter;
{$ELSE}
   Result := True;
{$ENDIF}
end;
procedure DoneDll;
begin
{$IFDEF DynamicLink}
  if HDll >= 32 then { success }
    FreeLibrary(HDll);
{$ENDIF}
  DllAvailable := False;
end;

initialization
  DllAvailable := InitDll;
finalization
  DoneDll;
end.


end.

