# Raylib 6.0 bindings

**URL:** <https://forum.ada-lang.io/t/raylib-6-0-bindings/4411>\
**Category:** General\
**Created:** [May 10, 2026, 4:11pm UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411 "2026-05-10T16:11:12Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![ZenitDS](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/zenitds/32/949_2.png) [@ZenitDS](https://forum.ada-lang.io/u/ZenitDS)\
**Post date:** [May 10, 2026, 4:11pm UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/1 "2026-05-10T16:11:12Z")

</div>

As I already commented in another post, I am working on some bindings for raylib. I open this one in order to have a dedicated thread for it.

> It should be noted that my experience in Ada is limited, and believe that I have made some unwise decisions. Hopefully someone can bring some of them up 🙂 .

For now, I have binded:

- `rcore` (windowing & input & timing & etc)
- `rcamera`
- `rshapes`
- `rtext` (partially)

* * *

## Design notes

I have chosen to split the library into packages as follows:

Types and conversions → `Raylib.Types` ( conversions are `To_C` and `To_Ada` )  
Function bindings → `Raylib.{Window,Draw,Time,Camera,Shapes,Text}`

Many conversions are mostly just direct and provided for uniformity. The remaining ones are just for converting between types.

Where a `const char *` was received, I changed them to take String and the use `Interfaces.C.Strings.New_String` and `Interfaces.C.Strings.Free` to convert to a C string.

One that I am concerned about is on functions that take a pointer to the first of several elements. e.g `Raylib.Shapes.Check_Collision_Point_Poly`.

I have modeled it this way:

```ada
---- Raylib.Types
--
-- Polygon[3D] - Set of points representing a polygon
--
   type Polygon is array (Natural range <>) of aliased Point
      with Convention => C;
   type Polygon3D is array (Natural range <>) of aliased Point3D
      with Convention => C;

---- Raylib.Shapes
   function Check_Collision_Point_Poly
            (Point : Vector2;
             Poly : Polygon) return Boolean is
      function CheckCollisionPointPoly
        (point : Vector2;
         points : access constant Vector2;
         pointCount : Int) return Bool;
      pragma Import (C, CheckCollisionPointPoly, "CheckCollisionPointPoly");
   begin
      return To_Ada (CheckCollisionPointPoly (Point,
                                              Poly(Poly'First)'Access,
                                              Int (Poly'Length)));
   end Check_Collision_Point_Poly;

```

* * *

## Roadmap

The bindings should be close to ready for use in basic 2D games. If anyone would like to give some feedback or contribute, it would be much appreciated.

This are some steps in the roadmap:

- Add a Math module equivalent to raymath
- Add support for more modules
- Package for alire (for this one a more experience hand would really help)

* * *

## Repository

> **[raylib-ada](https://codeberg.org/ZenitDS/raylib-ada)**
>
> Raylib bindings for the Ada programming language

> As a final note, I have used some generative AI for generating some bindings, but its use has been limited to basically copy-pasting and trivial changes

---

<div class="post-metadata">

**Author:** ![OneWingedShark](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/onewingedshark/32/305_2.png) [@OneWingedShark](https://forum.ada-lang.io/u/OneWingedShark)\
**Post date:** [May 11, 2026, 1:27am UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/2 "2026-05-11T01:27:13Z")

</div>

> [@ZenitDS](#):
>
> One that I am concerned about is on functions that take a pointer to the first of several elements. e.g `Raylib.Shapes.Check_Collision_Point_Poly`.

You might want to talk to @Lucretia about the best way to proceed, as he’s been doing the SDL binding, IIRC.

Though, personally, I prefer very thick bindings (i.e. all Ada from the POV of usage, with as little leak from abstractions as possible).

---

<div class="post-metadata">

**Author:** ![Lucretia](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/lucretia/32/17_2.png) [@Lucretia](https://forum.ada-lang.io/u/Lucretia)\
**Post date:** [May 11, 2026, 7:27am UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/3 "2026-05-11T07:27:30Z")

</div>

The best way forward for binding types is to remodel them and then come back later and restrict them when you find out their range, or do that at the same time if you can be bothered. Most C libs don’t really define ranges as they can’t really be bothered.

But essentially, instead of just having generic unsigned\_32, define new types of convention C, but that also means you need a well designed C API which is consistent where these types are passed, not all are.

Then obviously there are strings. The biggest issue here is the fact that conversions are done character by character which isn’t exactly fast and there’s no DMA way to do it, you’d literally need a DMA controller just to handle it if there was.

So, where strings are involved, you can wrap them with thicker bindings, i.e. passing in String and converting to chars\_ptr, char\_array and vice versa and remake all your strings so you don’t keep doing conversions especially inside any tight loops.

I still haven’t really worked out a good way around strings yet. Because inside any loops, you might want the C representation rather than Ada. Ada’s string conversions are not fast.

I’m not saying Ada is an outlier here, it’s not, all languages are slow when dealing with text and files and I/O to screen is a file. When I worked in games, I was logging to a file on every frame and it was slow af, disabled the logging and the fps went right back up, that was C++.

But you also need to understand that Ada does something else, it copies a lot, especially strings. If you return a string, that return value gets COPIED on return, it might even get copied multiple times.

Also, GNAT will convert a string literal to whatever it’s being passed to, so if it’s being passed to a C function, it’ll convert it IIRC.

---

<div class="post-metadata">

**Author:** ![dmitry-kazakov](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/dmitry-kazakov/32/522_2.png) [@dmitry-kazakov](https://forum.ada-lang.io/u/dmitry-kazakov)\
**Post date:** [May 11, 2026, 8:15am UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/4 "2026-05-11T08:15:02Z")

</div>

> [@Lucretia](#):
>
> I still haven’t really worked out a good way around strings yet. Because inside any loops, you might want the C representation rather than Ada. Ada’s string conversions are not fast.

Converting strings is perfectly OK when it is a _string_. But when a C library uses char \* for a buffer instead of void \* then bindings should treat it as an in-place buffer of Strorage\_Element and never copy it. E.g. if you are responsible for the buffer, you simply pass the address of the array element down to C and return back Last to indicate the updated chunk as the standard library does, e.g. Ada.Text\_IO.Get\_Line.

---

<div class="post-metadata">

**Author:** ![Fabien.C](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/fabien.c/32/46_2.png) [@Fabien.C](https://forum.ada-lang.io/u/Fabien.C)\
**Post date:** [May 11, 2026, 2:38pm UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/5 "2026-05-11T14:38:03Z")

</div>

I have updated my low-level bindings to Raylib 6.0: [Update for Raylib 6.0 · Fabien-Chouteau/raylib-ada@5751245 · GitHub](https://github.com/Fabien-Chouteau/raylib-ada/commit/5751245cbaadd7d7f23e87efa88f98a60c04c84b) available in Alire: [Raylib 2.0.0 (#1909) · alire-project/alire-index@ccc1c91 · GitHub](https://github.com/alire-project/alire-index/commit/ccc1c917f4c7ba817683b4c37e1d2d92f6ec5c73)

---

<div class="post-metadata">

**Author:** ![ZenitDS](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/zenitds/32/949_2.png) [@ZenitDS](https://forum.ada-lang.io/u/ZenitDS)\
**Post date:** [May 11, 2026, 5:23pm UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/6 "2026-05-11T17:23:58Z")

</div>

Hi,

I have taken a look at sdlada and it is really cool 🙂 . Probably will make use of it in the future. For the bindings, I have copied your approach of dividing into the Coordinate and Dimension types.

> [@Lucretia](#):
>
> But essentially, instead of just having generic unsigned\_32, define new types of convention C

Looks like a good idea to me, I am also taking that approach. At least to avoid programmer error and help to define intent it should be useful.

> [@Lucretia](#):
>
> I still haven’t really worked out a good way around strings yet. Because inside any loops, you might want the C representation rather than Ada. Ada’s string conversions are not fast.

For the strings, since there are few and small in use and in probably non-critical places for the meantime that should be not an issue for me.

---

<div class="post-metadata">

**Author:** ![dmitry-kazakov](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/dmitry-kazakov/32/522_2.png) [@dmitry-kazakov](https://forum.ada-lang.io/u/dmitry-kazakov)\
**Post date:** [May 11, 2026, 5:31pm UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/7 "2026-05-11T17:31:33Z")

</div>

> [@ZenitDS](#):
>
> Looks like a good idea to me, I am also taking that approach

Note that you can do that in a safe way:

` type Count is new Interfaces.C.unsigned; -- Still a C type`

---

<div class="post-metadata">

**Author:** ![Lucretia](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/lucretia/32/17_2.png) [@Lucretia](https://forum.ada-lang.io/u/Lucretia)\
**Post date:** [May 11, 2026, 5:34pm UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/8 "2026-05-11T17:34:40Z")

</div>

> [@dmitry-kazakov](#):
>
> Note that you can do that in a safe way:
> 
> ` type Count is new Interfaces.C.unsigned; -- Still a C type`

Better is:

`type Count is new Interfaces.Unsigned_32; -- Or whatever size it needs.`

---

<div class="post-metadata">

**Author:** ![dmitry-kazakov](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/dmitry-kazakov/32/522_2.png) [@dmitry-kazakov](https://forum.ada-lang.io/u/dmitry-kazakov)\
**Post date:** [May 11, 2026, 5:44pm UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/9 "2026-05-11T17:44:42Z")

</div>

That depends solely on how C declares it. If C says _unsigned_ then it is Interfaces.C.unsigned, because, for whatever reason, they wanted to make it machine-dependent. If it says _uint32\_t_ or something alike then it is Interfaces.Unsigned\_32.

---

<div class="post-metadata">

**Author:** ![ZenitDS](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/zenitds/32/949_2.png) [@ZenitDS](https://forum.ada-lang.io/u/ZenitDS)\
**Post date:** [May 12, 2026, 6:53am UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/10 "2026-05-12T06:53:11Z")

</div>

> [@dmitry-kazakov](#):
>
> Note that you can do that in a safe way:
> 
> ` type Count is new Interfaces.C.unsigned; -- Still a C type`

On this, how do you generally approach when the type is of the same name that the variables that you are naming? I find it difficult to find good names, specially in cases like this.

---

<div class="post-metadata">

**Author:** ![dmitry-kazakov](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/dmitry-kazakov/32/522_2.png) [@dmitry-kazakov](https://forum.ada-lang.io/u/dmitry-kazakov)\
**Post date:** [May 12, 2026, 7:32am UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/11 "2026-05-12T07:32:52Z")

</div>

I have no good answer. I tend to add some qualifier: File\_Length, Parameters\_Count.

---

<div class="post-metadata">

**Author:** ![ZenitDS](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/zenitds/32/949_2.png) [@ZenitDS](https://forum.ada-lang.io/u/ZenitDS)\
**Post date:** [May 12, 2026, 8:17am UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/12 "2026-05-12T08:17:33Z")

</div>

> [@Lucretia](#):
>
> Better is:
> 
> `type Count is new Interfaces.Unsigned_32; -- Or whatever size it needs.`

That would be better if possible. Bad thing that many programs just assume that `unsigned int` refers to 32-bit without stating it ☹ . I think I will stick with `Interfaces.C.unsigned` for `unsigned int` as cited by @dmitry-kazakov.

---

<div class="post-metadata">

**Author:** ![ZenitDS](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/zenitds/32/949_2.png) [@ZenitDS](https://forum.ada-lang.io/u/ZenitDS)\
**Post date:** [May 12, 2026, 1:31pm UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/13 "2026-05-12T13:31:07Z")

</div>

Another quick question. Is it possible to expose the “+”, “-”, etc functions for all types in a given package without polluting the namespace with other elements?

e.g. make the following work, where Value is added 1.

```ada
package A is
   type A is new Integer;
end A;

-- Other File
with A;

package B is
   procedure P (Value : A) is
   begin
      return Value + 1;
   end P;
end B;

```

---

<div class="post-metadata">

**Author:** ![dmitry-kazakov](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/dmitry-kazakov/32/522_2.png) [@dmitry-kazakov](https://forum.ada-lang.io/u/dmitry-kazakov)\
**Post date:** [May 12, 2026, 2:22pm UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/14 "2026-05-12T14:22:36Z")

</div>

There is [use type](https://www.adaic.org/resources/add_content/standards/22aarm/html/AA-8-4.html#I4716) clause.

You must also consider yourself in either of two camps: **use-lovers** and **use-haters**. So make your design use-clause-friendly or else ask the government to reduce VAT on extra wide displays. 😀

Be careful with renaming. Renaming is broken in Ada:

- Renaming introduces name conflict even if conflicting names resolve to the same entity. You will see that on example of exceptions when _Data\_Error_ gets suddenly invisible if you **use** -ed standard library packages renaming it.
- Renaming ignores constraints (subtypes). When you rename to a constrained subtype or to different array bounds (for index sliding) you are asking for trouble:

```ada
   S : String (4..8) := "4567";
   subtype Sliding is String (1..4);
   T : Sliding renames S;

```

`T (1)` is Constraint\_Error. Subtype indication in a renaming is basically a lie.

Note that renaming creates an object. This is why renaming a function call does its result. It is not a lazy expression re-evaluated on each reference as in FORTRAN. In Ada 95 times renaming a result was used in hope that the compiler will not copy the result and deploy a managed reference instead:

```ada
   S1 : constant String := Get_Line; -- Read line, copy it
   S2 : String renames Get_Line; -- Read line, return a managed reference

```

In these days it would be same, I guess.

**BUT**. Always rename[\*] formal types of a generic. Generics are complicated. GNAT and/or the language always has bugs related to visibility in generics. If GNAT refuses to recognize a formal type, use its renaming.

[\*] Types are renamed using `subtype S is T`.

---

<div class="post-metadata">

**Author:** ![OneWingedShark](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/onewingedshark/32/305_2.png) [@OneWingedShark](https://forum.ada-lang.io/u/OneWingedShark)\
**Post date:** [May 12, 2026, 8:47pm UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/15 "2026-05-12T20:47:52Z")

</div>

> [@ZenitDS](#):
>
> On this, how do you generally approach when the type is of the same name that the variables that you are naming? I find it difficult to find good names, specially in cases like this.

Try to use names that ‘make sense’; there are several ways to overcome this sort of name-clash.  
One is to have a set of packages where the type is `Instance` and the package full-name describes the _what_ — e.g. in package `GUI.Common.Button` having a type, `Instance`; in these sorts of situations, I rather like naming parameters `Object`, so you might have `Procedure Init( Object : out Instance; Parent : in out GUI.Base.Instance'Class; Text : String; X, Y, H, W : Natural );`. (I’m not 100% in the type `Instance` camp, but it is acceptable in well-segmented & consistent libraries.)

> [@ZenitDS](#):
>
> Another quick question. Is it possible to expose the “+”, “-”, etc functions for all types in a given package without polluting the namespace with other elements?

This is what `Use type Whatever;` does.  
But you can also consider using `use` in the best scope that uses it; I’m not in the ‘haters’ group, but not the ‘lovers’ either, let how much you use/depend on the namespace to guide your use of `use`: if, for example, you’re writing a library that does string manipulations, then `Use Ada.Strings.Fixed` is likely going to be appropriate, if you’re using some geometry package in some GUI, then perhaps in a declare where the operations are needed, if there’s a lot of the `use` of that, than the body of the subprogram, if many subprograms than the translation-unit itself.

---

<div class="post-metadata">

**Author:** ![ZenitDS](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/zenitds/32/949_2.png) [@ZenitDS](https://forum.ada-lang.io/u/ZenitDS)\
**Post date:** [May 12, 2026, 9:44pm UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/16 "2026-05-12T21:44:23Z")

</div>

hmmm. 🤔 I take note.

I finally put the whole bindings into a single file and package `Raylib`.

I guess that the preferred approach will be to use `use type Coordinate`, etc whenever possible. Else you could just `use` the whole `Raylib`, which would make for very close behavior to C. 🤷

---

<div class="post-metadata">

**Author:** ![OneWingedShark](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/onewingedshark/32/305_2.png) [@OneWingedShark](https://forum.ada-lang.io/u/OneWingedShark)\
**Post date:** [May 13, 2026, 4:05am UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/17 "2026-05-13T04:05:01Z")

</div>

> [@ZenitDS](#):
>
> I finally put the whole bindings into a single file and package `Raylib`.

Interesting.  
I’m working on a library myself, and it’s got quite a lot of parts, so I’m sometimes using a lot of other dependencies, consider in an package body:

```ada
Function Get_Bytes(Name : String) return String is
  Use System.Storage_Elements;

  Package IO is new Ada.Direct_IO( Storage_Element );
  Use IO;

  Function Get_File return File_Type is
  Begin
     Return Result : File_Type do
       Open( File => Result, Mode => In_File, Name => File_Name );
     End return;
  End Get_File;

  File : File_Type:= Get_File;
Begin
  Return Result : String(1..Natural(Size(File))) do
    For X in Result'Range loop
      Declare
        C : Character renames Result(X);
        E : Storage_Element with Import, Address => C'Address;
      Begin
        Read( Item => E, File => File );
      End;
    End loop;
    Close( File );
  End return;
End Get_Bytes;

```

As you can see, I’ve omitted prefixing the internals with `System.Storage_Elements` and `IO` via `use`, ‘factoring’ them to the outermost scopes of the function, yet having these namespaces exposed in the implementation does not ‘bleed’ into the rest of the functions in the package. (Yes, I could have used `Character` directly on `Direct_IO`’s instantiation, or just used `Text_IO`, but the point was giving some sort of example.)

---

<div class="post-metadata">

**Author:** ![ZenitDS](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/zenitds/32/949_2.png) [@ZenitDS](https://forum.ada-lang.io/u/ZenitDS)\
**Post date:** [May 14, 2026, 1:12pm UTC](https://forum.ada-lang.io/t/raylib-6-0-bindings/4411/18 "2026-05-14T13:12:31Z")

</div>

Finally split the math module into a separate package Raylib.Math that has `subtype`’s and renames for the `Coordinate`, `Dimension`, `Vector2`, etc. Which you will normally want to use in videogame math. Then you just `use` Raylib.Math and that gives you all the types and functions for math operations.

P.S.  
Operator overloading gives me mixed feelings, nonetheless it is pretty nice.  
The type system rocks seems like will save me a bunch of time in the long term.
