Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 50 additions & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,56 @@ Ada's strong typing provides additional safety when calling Zig code:

== Examples

See the `examples/` directory for complete working examples.
The `examples/` directory contains complete working examples:

=== Basic Example

Demonstrates calling Zig functions from Ada:

[source,bash]
----
cd examples
gprbuild -P examples.gpr basic_example.adb
./bin/basic_example
----

Features demonstrated:
* Version information retrieval
* Arithmetic operations (add, multiply)
* Mathematical functions (factorial, fibonacci)
* String operations

=== Callback Example

Demonstrates bidirectional FFI with callbacks from Zig to Ada:

[source,bash]
----
cd examples
gprbuild -P examples.gpr callback_example.adb
./bin/callback_example
----

Features demonstrated:
* Registering Ada procedures as callbacks
* Invoking callbacks from Zig
* Iterator pattern with Ada-style termination control

=== Safety Example

Demonstrates safety-critical patterns with error handling:

[source,bash]
----
cd examples
gprbuild -P examples.gpr safety_example.adb
./bin/safety_example
----

Features demonstrated:
* Safe division with error callbacks
* Bounds-checked array access
* Buffer operations

== RSR Compliance

Expand Down
54 changes: 54 additions & 0 deletions examples/basic_example.adb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
-- SPDX-License-Identifier: AGPL-3.0-or-later
-- Basic Example: Demonstrates calling Zig functions from Ada

with Ada.Text_IO;
with Interfaces.C;
with Zig_FFI;

procedure Basic_Example is
use Ada.Text_IO;
use Interfaces.C;
begin
Put_Line ("=== Ada-Zig-FFI Basic Example ===");
Put_Line ("");

-- Version information
declare
Version : constant unsigned := Zig_FFI.Get_Version;
Major : constant unsigned := Version / 2**16;
Minor : constant unsigned := (Version / 2**8) mod 2**8;
Patch : constant unsigned := Version mod 2**8;
begin
Put_Line ("Library Version:" &
Major'Image & "." &
Minor'Image & "." &
Patch'Image);
end;
Put_Line ("");

-- Arithmetic operations
Put_Line ("--- Arithmetic Operations ---");
Put_Line ("Add (5, 3) =" & Zig_FFI.Add (5, 3)'Image);
Put_Line ("Multiply (7, 6) =" & Zig_FFI.Multiply (7, 6)'Image);
Put_Line ("");

-- Mathematical functions
Put_Line ("--- Mathematical Functions ---");
Put_Line ("Factorial (5) =" & Zig_FFI.Factorial (5)'Image);
Put_Line ("Factorial (10) =" & Zig_FFI.Factorial (10)'Image);
Put_Line ("Fibonacci (10) =" & Zig_FFI.Fibonacci (10)'Image);
Put_Line ("Fibonacci (20) =" & Zig_FFI.Fibonacci (20)'Image);
Put_Line ("");

-- String operations
Put_Line ("--- String Operations ---");
declare
Test_String : constant char_array := To_C ("Hello, Ada-Zig-FFI!");
begin
Put_Line ("String_Length (""Hello, Ada-Zig-FFI!"") =" &
Zig_FFI.String_Length (Test_String)'Image);
end;
Put_Line ("");

Put_Line ("=== Example Complete ===");
end Basic_Example;
64 changes: 64 additions & 0 deletions examples/callback_example.adb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
-- SPDX-License-Identifier: AGPL-3.0-or-later
-- Callback Example: Demonstrates bidirectional FFI with callbacks

with Ada.Text_IO;
with Interfaces.C;
with Zig_FFI;

procedure Callback_Example is
use Ada.Text_IO;
use Interfaces.C;

-- Callback procedure that will be called from Zig
procedure My_Int_Handler (Value : int)
with Convention => C;

procedure My_Int_Handler (Value : int) is
begin
Put_Line (" [Ada callback received] Value:" & Value'Image);
end My_Int_Handler;

-- Iterator callback that returns control signal
function My_Iterator_Handler (Value : int) return int
with Convention => C;

function My_Iterator_Handler (Value : int) return int is
begin
Put_Line (" [Iterator] Processing:" & Value'Image);
-- Return 0 to continue, non-zero to stop
if Value >= 5 then
Put_Line (" [Iterator] Stopping at 5");
return 1; -- Stop iteration
end if;
return 0; -- Continue
end My_Iterator_Handler;

begin
Put_Line ("=== Ada-Zig-FFI Callback Example ===");
Put_Line ("");

-- Register and invoke int callback
Put_Line ("--- Int Callback Demo ---");
Zig_FFI.Register_Int_Callback (My_Int_Handler'Access);
Put_Line ("Invoking callback with value 42:");
Zig_FFI.Invoke_Int_Callback (42);
Put_Line ("Invoking callback with value -100:");
Zig_FFI.Invoke_Int_Callback (-100);
Put_Line ("");

-- Iterator pattern demonstration
Put_Line ("--- Iterator Pattern Demo ---");
Put_Line ("Iterating from 1 to 10 with step 1 (stopping at 5):");
declare
Count : constant int := Zig_FFI.For_Each_In_Range
(Start => 1,
Stop => 10,
Step => 1,
Handler => My_Iterator_Handler'Access);
begin
Put_Line ("Iterations completed:" & Count'Image);
end;
Put_Line ("");

Put_Line ("=== Example Complete ===");
end Callback_Example;
35 changes: 35 additions & 0 deletions examples/examples.gpr
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
-- SPDX-License-Identifier: AGPL-3.0-or-later
-- Examples Project File

with "../ada_zig_ffi.gpr";

project Examples is

for Source_Dirs use (".");
for Object_Dir use "obj";
for Exec_Dir use "bin";

for Main use ("basic_example.adb", "callback_example.adb", "safety_example.adb");

package Compiler is
for Default_Switches ("Ada") use
("-gnat2022", -- Ada 2022
"-gnatwa", -- All warnings
"-gnatyM120", -- Max line length 120
"-gnata", -- Enable assertions
"-gnatVa", -- Validity checks
"-O2"); -- Optimization
end Compiler;

package Linker is
for Default_Switches ("Ada") use
("-L../zig-lib/zig-out/lib",
"-lzigffi",
"-Wl,-rpath,../zig-lib/zig-out/lib");
end Linker;

package Binder is
for Default_Switches ("Ada") use ("-E");
end Binder;

end Examples;
117 changes: 117 additions & 0 deletions examples/safety_example.adb
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
-- SPDX-License-Identifier: AGPL-3.0-or-later
-- Safety Example: Demonstrates safety-critical patterns with error handling

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

procedure Safety_Example is
use Ada.Text_IO;
use Interfaces.C;

-- Error callback for division by zero
procedure Division_Error_Handler (Message : char_array)
with Convention => C;

procedure Division_Error_Handler (Message : char_array) is
begin
Put_Line (" [ERROR] Division error: " & To_Ada (Message));
end Division_Error_Handler;

-- Bounds error callback for array access violations
procedure Bounds_Error_Handler (Index : size_t; Length : size_t)
with Convention => C;

procedure Bounds_Error_Handler (Index : size_t; Length : size_t) is
begin
Put_Line (" [ERROR] Bounds violation: index" &
Index'Image & " >= length" & Length'Image);
end Bounds_Error_Handler;

begin
Put_Line ("=== Ada-Zig-FFI Safety Example ===");
Put_Line ("");

-- Safe division demonstration
Put_Line ("--- Safe Division Demo ---");
declare
Result : aliased int;
Status : int;
begin
-- Successful division
Put_Line ("Safe_Divide (100, 4):");
Status := Zig_FFI.Safe_Divide
(Numerator => 100,
Denominator => 4,
Result => Result'Access,
Error_Cb => null);
if Status = 0 then
Put_Line (" Result:" & Result'Image);
end if;

-- Division by zero with error callback
Put_Line ("Safe_Divide (50, 0) - with error callback:");
Status := Zig_FFI.Safe_Divide
(Numerator => 50,
Denominator => 0,
Result => Result'Access,
Error_Cb => Division_Error_Handler'Access);
if Status /= 0 then
Put_Line (" Operation failed (as expected)");
end if;
end;
Put_Line ("");

-- Bounds-checked array access demonstration
Put_Line ("--- Bounds-Checked Array Access Demo ---");
declare
type Int_Array is array (0 .. 4) of aliased int
with Convention => C;

Data : Int_Array := (10, 20, 30, 40, 50);
Result : aliased int;
Status : int;
begin
-- Successful access
Put_Line ("Accessing Data (3) - valid index:");
Status := Zig_FFI.Checked_Array_Access
(Arr => Data (0)'Address,
Len => Data'Length,
Index => 3,
Result => Result'Access,
Bounds_Error => null);
if Status = 0 then
Put_Line (" Value at index 3:" & Result'Image);
end if;

-- Out of bounds access with error callback
Put_Line ("Accessing Data (10) - invalid index:");
Status := Zig_FFI.Checked_Array_Access
(Arr => Data (0)'Address,
Len => Data'Length,
Index => 10,
Result => Result'Access,
Bounds_Error => Bounds_Error_Handler'Access);
if Status /= 0 then
Put_Line (" Access failed (as expected)");
end if;
end;
Put_Line ("");

-- Buffer sum demonstration
Put_Line ("--- Buffer Sum Demo ---");
declare
type Byte_Array is array (0 .. 4) of aliased Interfaces.C.unsigned_char
with Convention => C;

Data : Byte_Array := (1, 2, 3, 4, 5);
Sum : unsigned_long;
begin
Sum := Zig_FFI.Buffer_Sum (Data (0)'Address, Data'Length);
Put_Line ("Buffer_Sum ([1, 2, 3, 4, 5]) =" & Sum'Image);
end;
Put_Line ("");

Put_Line ("=== Example Complete ===");
end Safety_Example;
Loading
Loading