How to resolve the algorithm Call a function in a shared library step by step in the Ada programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Call a function in a shared library step by step in the Ada programming language

Table of Contents

Problem Statement

Show how to call a function in a shared library (without dynamically linking to it at compile-time). In particular, show how to call the shared library function if the library is available, otherwise use an internal equivalent function. This is a special case of calling a foreign language function where the focus is close to the ABI level and not at the normal API level.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Call a function in a shared library step by step in the Ada programming language

Source code in the ada programming language

with Ada.Text_IO;   use Ada.Text_IO;
with Interfaces;    use Interfaces;
with Interfaces.C;  use Interfaces.C;
with System;        use System;

with Ada.Unchecked_Conversion;

procedure Shared_Library_Call is
   --
   -- Interface to kernel32.dll which is responsible for loading DLLs under Windows.
   -- There are ready to use Win32 bindings. We don't want to use them here.
   --
   type HANDLE is new Unsigned_32; -- on x64 system, replace by Unsigned_64 to make it work
   function LoadLibrary (lpFileName : char_array) return HANDLE;
   pragma Import (stdcall, LoadLibrary, "LoadLibrary", "_LoadLibraryA"); -- Ada95 does not have the @n suffix.

   function GetProcAddress (hModule : HANDLE; lpProcName : char_array)
      return Address;
   pragma Import (stdcall, GetProcAddress, "GetProcAddress", "_GetProcAddress"); --
   --
   -- The interface of the function we want to call. It is a pointer (access type)
   -- because we will link it dynamically. The function is from User32.dll
   --
   type MessageBox is access function 
        (  hWnd      : Address     := Null_Address;
           lpText    : char_array;
           lpCaption : char_array  := To_C ("Greeting");
           uType     : Unsigned_16 := 0
        )  return Integer_16;
   pragma Convention (Stdcall, MessageBox);
   function To_MessageBox is new Ada.Unchecked_Conversion (Address, MessageBox);

   Library : HANDLE  := LoadLibrary (To_C ("user32.dll"));
   Pointer : Address := GetProcAddress (Library, To_C ("MessageBoxA"));
begin
   if Pointer /= Null_Address then
      declare
         Result : Integer_16;
      begin
         Result := To_MessageBox (Pointer) (lpText => To_C ("Hello!"));
      end;
   else
      Put_Line ("Unable to load the library " & HANDLE'Image (Library));
   end if;
end Shared_Library_Call;


with Ada.Environment_Variables;  use Ada.Environment_Variables;
with Ada.Text_IO;                use Ada.Text_IO;
with Interfaces;                 use Interfaces;
with Interfaces.C;               use Interfaces.C;
with System;                     use System;

with Ada.Unchecked_Conversion;

procedure Shared_Library_Call is
   --
   -- Interface to libdl to load dynamically linked libraries
   --
   function dlopen (FileName : char_array; Flag : int) return Address;
   pragma Import (C, dlopen);

   function dlsym (Handle : address; Symbol : char_array) return Address;
   pragma Import (C, dlsym);
   --
   -- The interfaces of the functions we want to call. These are pointers
   -- (access type) because we will link it dynamically. The functions
   -- come from libX11.so.
   --
   type XOpenDisplay is access function (Display_Name : char_array) return Address;
   pragma Convention (C, XOpenDisplay);
   function To_Ptr is new Ada.Unchecked_Conversion (Address, XOpenDisplay);

   type XDisplayWidth is access function (Display : Address; Screen : int) return int;
   pragma Convention (C, XDisplayWidth);
   function To_Ptr is new Ada.Unchecked_Conversion (Address, XDisplayWidth);

   Library : Address := dlopen (To_C ("libX11.so"), 1);
   OpenDisplay  : XOpenDisplay  := To_Ptr (dlsym (Library, To_C ("XOpenDisplay")));
   DisplayWidth : XDisplayWidth := To_Ptr (dlsym (Library, To_C ("XDisplayWidth")));
begin
   if OpenDisplay /= null and then DisplayWidth /= null then
      declare
         Display : Address;
      begin
         Display := OpenDisplay (To_C (Value ("DISPLAY")));
         if Display = Null_Address then
            Put_Line ("Unable to open display " & Value ("DISPLAY"));
         else
            Put_Line (Value ("DISPLAY") & " width is" & int'image (DisplayWidth (Display, 0)));
         end if;
      end;
   else
      Put_Line ("Unable to load the library");
   end if;
end Shared_Library_Call;


  

You may also check:How to resolve the algorithm Hello world/Newline omission step by step in the HolyC programming language
You may also check:How to resolve the algorithm Align columns step by step in the D programming language
You may also check:How to resolve the algorithm Compiler/code generator step by step in the Scala programming language
You may also check:How to resolve the algorithm Sort an array of composite structures step by step in the Babel programming language
You may also check:How to resolve the algorithm Strong and weak primes step by step in the PureBasic programming language