# Simple type cast?

**URL:** <https://forum.crystal-lang.org/t/simple-type-cast/7588>\
**Category:** Help & Support\
**Created:** [January 10, 2025, 11:22pm UTC](https://forum.crystal-lang.org/t/simple-type-cast/7588 "2025-01-10T23:22:26Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![emrum](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/emrum/32/2749_2.png) [@emrum](https://forum.crystal-lang.org/u/emrum)\
**Post date:** [January 10, 2025, 11:22pm UTC](https://forum.crystal-lang.org/t/simple-type-cast/7588/1 "2025-01-10T23:22:26Z")

</div>

lib LibJack  
type Nframes = UInt32  
end

tm : LibJack::Nframes = 0\_u32  
Error: type must be LibJack::Nframes, not UInt32

tm : LibJack::Nframes = 0\_u32.as(LibJack::Nframes)  
Error: can’t cast UInt32 to LibJack::Nframes

tm : LibJack::Nframes = LibJack::Nframes.new(0\_u32)  
Error: undefined method ‘new’ for LibJack::Nframes.class

cannot cast UInt32 to UInt32 ???

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [January 10, 2025, 11:44pm UTC](https://forum.crystal-lang.org/t/simple-type-cast/7588/2 "2025-01-10T23:44:31Z")

</div>

you probably want to use `alias` instead of `type`. `type` is a bit more strict and has a bit more specialized use case.

- [alias - Crystal](https://crystal-lang.org/reference/1.14/syntax_and_semantics/alias.html)
- [type - Crystal](https://crystal-lang.org/reference/1.14/syntax_and_semantics/c_bindings/type.html)

---

<div class="post-metadata">

**Author:** ![yxhuvud](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/yxhuvud/32/27_2.png) [@yxhuvud](https://forum.crystal-lang.org/u/yxhuvud)\
**Post date:** [January 11, 2025, 9:44am UTC](https://forum.crystal-lang.org/t/simple-type-cast/7588/3 "2025-01-11T09:44:42Z")

</div>

Oh, you have started to make bindings to Jack? Cool! I’ve started a little with pipewire bindings, though I havn’t gotten that far yet…

---

<div class="post-metadata">

**Author:** ![emrum](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/emrum/32/2749_2.png) [@emrum](https://forum.crystal-lang.org/u/emrum)\
**Post date:** [January 11, 2025, 1:59pm UTC](https://forum.crystal-lang.org/t/simple-type-cast/7588/4 "2025-01-11T13:59:02Z")

</div>

the type def is “a bit more strict” == unusable ?  
it’s hard to imagine why a cast of Int32 to Int32 might case any issue.

---

<div class="post-metadata">

**Author:** ![emrum](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/emrum/32/2749_2.png) [@emrum](https://forum.crystal-lang.org/u/emrum)\
**Post date:** [January 11, 2025, 2:01pm UTC](https://forum.crystal-lang.org/t/simple-type-cast/7588/5 "2025-01-11T14:01:40Z")

</div>

yes, here is the header for jackd audio, in case you need it, although very untestet yet:

```auto

@[Link("jack")]
lib LibJack
  # JACK API types
  alias Nframes = UInt32
  alias Client = Void*
  alias Port = Void*
  
  # Client management
  fun client_open = jack_client_open(name : LibC::Char*, options : Int32, status : Int32*) : Client
  fun client_close = jack_client_close(client : Client) : Int32
  fun client_name_size = jack_client_name_size : Int32
  
  # Port management
  fun port_register = jack_port_register(client : Client, name : LibC::Char*, type : LibC::Char*, flags : UInt64, buffer_size : UInt64) : Port
  fun port_unregister = jack_port_unregister(client : Client, port : Port) : Int32
  fun port_get_buffer = jack_port_get_buffer(port : Port, nframes : Nframes) : Void*
  
  # Transport
  fun transport_start = jack_transport_start(client : Client)
  fun transport_stop = jack_transport_stop(client : Client)
  fun transport_locate = jack_transport_locate(client : Client, frame : Nframes)
  
  # Callbacks
  alias ProcessCallback = (Nframes, Void*) -> Int32
  alias ShutdownCallback = (Void*) -> Void
  alias XRunCallback = (Void*) -> Void
  
  fun set_process_callback = jack_set_process_callback(client : Client, callback : ProcessCallback, arg : Void*) : Int32
  fun on_shutdown = jack_on_shutdown(client : Client, callback : ShutdownCallback, arg : Void*)
  fun set_xrun_callback = jack_set_xrun_callback(client : Client, callback : XRunCallback, arg : Void*) : Int32
  
  # Client activation
  fun activate = jack_activate(client : Client) : Int32
  fun deactivate = jack_deactivate(client : Client) : Int32
  
  # Time and tempo
  fun get_sample_rate = jack_get_sample_rate(client : Client) : UInt32
  fun get_buffer_size = jack_get_buffer_size(client : Client) : UInt32
  fun frame_time = jack_frame_time(client : Client) : Nframes
end

```

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [January 11, 2025, 2:08pm UTC](https://forum.crystal-lang.org/t/simple-type-cast/7588/6 "2025-01-11T14:08:40Z")

</div>

> [@emrum](#):
>
> the type def is “a bit more strict” == unusable ?

Its use case would make sense for your `client_open` function. If you make it `type Client = Void*` then the compiler would know that you can’t just pass any `Void*` to say `client_close`. It would only allow the return value of `client_open` since that’s the only function that returns a `Client` explicitly.

---

<div class="post-metadata">

**Author:** ![emrum](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/emrum/32/2749_2.png) [@emrum](https://forum.crystal-lang.org/u/emrum)\
**Post date:** [January 11, 2025, 6:20pm UTC](https://forum.crystal-lang.org/t/simple-type-cast/7588/7 "2025-01-11T18:20:28Z")

</div>

yes, i like defining types, but if I cannot cast them (explicitly), in certain case it can become big trouble.

---

<div class="post-metadata">

**Author:** ![bcardiff](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/bcardiff/32/3_2.png) [@bcardiff](https://forum.crystal-lang.org/u/bcardiff)\
**Post date:** [January 11, 2025, 10:26pm UTC](https://forum.crystal-lang.org/t/simple-type-cast/7588/8 "2025-01-11T22:26:32Z")

</div>

I agree that being able to define custom types wrapping Ints has it’s uses.

You can use `unsafe_as` thought it seems to have some rough edges.

Given,

```crystal
lib L
  type T = Int32
end

```

Although the following complains

```auto
0.as(L::T)
          ^
Error: can't cast Int32 to L::T

```

The following works

```crystal
0.unsafe_as(L::T)

```

The rough edges are:

```crystal
v = 0.unsafe_as(L::T)
pp! typeof(v) # => Int32 (but is a L::T 🐛)
pp! v.class # => Int32 (but is a L::T 🐛)

```

And `L::T#to_s` will not work

```crystal
v = 0.unsafe_as(L::T)
pp! v

```

```auto
There was a problem expanding macro 'macro_4743351584'

Code in src/int.cr:185:5

 185 | {% begin %}
       ^
Called macro defined in src/int.cr:185:5

 185 | {% begin %}

Which expanded to:

 > 2 | if other == 0
 > 3 | raise DivisionByZeroError.new
 > 4 | elsif self < 0 && self == L::T::MIN && other == -1
                                 ^--------
Error: undefined constant L::T::MIN

```

And `L::T` are autocasted as `Int32` if needed during def matching but then expanded using the original type.

```auto
def x(a : Int32)
  a
end

v = 0.unsafe_as(L::T)
x(v)

```

This works, but `x(v) : L::T` as shown if you do `pp! x(v)`. Because you will get the previous error (not having a `L::T::MIN`).

---

<div class="post-metadata">

**Author:** ![yxhuvud](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/yxhuvud/32/27_2.png) [@yxhuvud](https://forum.crystal-lang.org/u/yxhuvud)\
**Post date:** [January 12, 2025, 11:14am UTC](https://forum.crystal-lang.org/t/simple-type-cast/7588/9 "2025-01-12T11:14:23Z")

</div>

> [@emrum](#):
>
> the type def is “a bit more strict” == unusable ?

Depends on what you do with it. For example, I’ve found bugs when replacing alias with type as it no longer saw pointers to several different struct types defined as Void as equal. Generally I’d recommend wrapping the raw C bindings with more convenient things when possible instead of exposing them to end users. The C API often don’t make sense from a crystal perspective anyhow.
