# How to safely cast C union types / use pointer\_from\_objref?

**URL:** <https://discourse.julialang.org/t/how-to-safely-cast-c-union-types-use-pointer-from-objref/40162>\
**Category:** General Usage\
**Created:** [May 26, 2020, 1:44am UTC](https://discourse.julialang.org/t/how-to-safely-cast-c-union-types-use-pointer-from-objref/40162 "2020-05-26T01:44:59Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![ColinCaine](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colincaine/32/7211_2.png) [@ColinCaine](https://discourse.julialang.org/u/ColinCaine)\
**Post date:** [May 26, 2020, 1:44am UTC](https://discourse.julialang.org/t/how-to-safely-cast-c-union-types-use-pointer-from-objref/40162/1 "2020-05-26T01:44:59Z")

</div>

I have a function, that accepts a pointer to a Julia allocated object, fills it with data, and returns it. I then want to cast that object to another type and do stuff with it. How can I best do that without risking the GC eating the memory allocated for the original object?

Code example:

```julia
# Allocate an empty struct in Julia
event = SDL.Event(undef)

# Get C to populate that struct
SDL.PollEvent(Ref(event))

if (event.type == SDL.WindowEvent)
    windowevent = unsafe_load( Ptr{SDL.WindowEvent}(pointer_from_objref(event)) )
    # I think this next line is unsafe.
    return windowevent
end

```

My questions:

1. When is `event` allowed to be garbage collected?
2. Can I safely return `windowevent` here? (from the `pointer_from_objref` docs, I don’t think so)
3. Is there any way to tell Julia that I want `windowevent` to own `event`’s memory / extend its lifetime?

The approaches I’ve come up with are:

1. Accept a callback and use `do` syntax to make it mostly okay
2. Take a copy of the loaded windowevent
3. Define new structs for each event type that keep a reference to their data (sounds like a lot of work)

Here’s how I’m imagining implementing option 1:

```julia
function pollevent(f)
    event = SDL.Event(undef)
    GC.@preserve event begin
        SDL.PollEvent(event)
        # cast event to the right type
        # ...
       
        # give the casted object to f
        f(event)
    end
end

# Use example
pollevent() do e
    # do something
end

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [May 26, 2020, 2:22am UTC](https://discourse.julialang.org/t/how-to-safely-cast-c-union-types-use-pointer-from-objref/40162/2 "2020-05-26T02:22:58Z")

</div>

> [@ColinCaine](#):
>
> - When is `event` allowed to be garbage collected?

It doesn’t have to exist, so never or before any allocation.

> [@ColinCaine](#):
>
> - Can I safely return `windowevent` here? (from the `pointer_from_objref` docs, I don’t think so)

Returning is fine. The load that creates it is not.

> [@ColinCaine](#):
>
> 1. Is there any way to tell Julia that I want `windowevent` to own `event` 's memory / extend its lifetime?

No and it’s not owning that memory anyway.

> [@ColinCaine](#):
>
> - Take a copy of the loaded windowevent

You are doing that already.

> [@ColinCaine](#):
>
> ```julia
> SDL.PollEvent(Ref(event))
> 
> ```

It’s also unclear what this is trying to do. In particular, it’s unclear what the `Ref` is doing here. The `Ref` is not creating anything magic about the `event` calling it here is the same as calling it in `PollEvent`. If `event` is a mutable object and the Ref is just what’s needed to call the C function, you should just move where the `Ref` call is. If `event` is a immutable object, this will not cause `event` to be mutated (in this case `pointer_from_objref` is also completely invalid).

Now without more context, it’s also unclear why you are creating a event rather than a windowevent in the first place.

---

<div class="post-metadata">

**Author:** ![ColinCaine](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colincaine/32/7211_2.png) [@ColinCaine](https://discourse.julialang.org/u/ColinCaine)\
**Post date:** [May 26, 2020, 11:17am UTC](https://discourse.julialang.org/t/how-to-safely-cast-c-union-types-use-pointer-from-objref/40162/3 "2020-05-26T11:17:07Z")

</div>

Thanks for your response.

> If `event` is a mutable object and the Ref is just what’s needed to call the C function, you should just move where the `Ref` call is.

Yes, PollEvent is a C function that accepts a pointer, Ref is giving me a pointer. I’ll move it up:

```julia
event = Ref(SDL.Event(undef))

```

> Now without more context, it’s also unclear why you are creating a event rather than a windowevent in the first place.

The Event is a C union type of a bunch of more specific events. In this context I want to return a WindowEvent if the type field indicates it is a WindowEvent; or a KeyboardEvent if; or a MouseEvent; etc.

I don’t know until I look at the object at run-time what type it should be.

> immutable

If SDL.Event is an immutable struct and I make a Ref to it, is pointer\_from\_objref okay to be applied to the reference?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [May 26, 2020, 12:39pm UTC](https://discourse.julialang.org/t/how-to-safely-cast-c-union-types-use-pointer-from-objref/40162/4 "2020-05-26T12:39:35Z")

</div>

> [@ColinCaine](#):
>
> Yes, PollEvent is a C function that accepts a pointer, Ref is giving me a pointer. I’ll move it up:

`Ref` does **NOT** give you a pointer. It is, though, the standard mutable container for a immutable object so that you can get the return value. In that case you **must** accss the `Ref` after the call. Calling `SDL.PollEvent(Ref(event))` will do nothing to `event`.

> [@ColinCaine](#):
>
> If SDL.Event is an immutable struct and I make a Ref to it, is pointer\_from\_objref okay to be applied to the reference?

The `Ref` is not a “reference” and you don’t get a Ref “to” the immutable object in any sense that you might be thinking about it. What you’ve created by calling `Ref` is not very different from a single element array of the object, just more efficient and with a few convinient methods defined for it to make it easier to use when dealing with C. There’s very little special about `Ref` apart from `ccall` handling of it.

Back to the code, doing `pointer_from_objref` on the `Ref` is OK, though you do need to `GC.@preserve` the input argument to `pointer_from_objref` for as long as you use the returnend pointer to access the underlaying memory.

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [May 26, 2020, 12:58pm UTC](https://discourse.julialang.org/t/how-to-safely-cast-c-union-types-use-pointer-from-objref/40162/5 "2020-05-26T12:58:08Z")

</div>

@ColinCaine The following implementation of `sfEvent` might be of interest to you. It’s from SFML library, but SDL has a similar design for its event union.

> <https://github.com/JuliaMultimedia/CSFML.jl/blob/3bc0de32390ea821eb9471acca90d1c7c2ad5d97/src/Window/window_common.jl#L272-L314>

By doing this, you could use it just like a C union, for example,

> <https://github.com/JuliaMultimedia/CSFML.jl/blob/3bc0de32390ea821eb9471acca90d1c7c2ad5d97/examples/short_example.jl#L27-L45>

BTW, @jonathanBieler maintains an SDL2 wrapper [here](https://github.com/jonathanBieler/SimpleDirectMediaLayer.jl).

---

<div class="post-metadata">

**Author:** ![ColinCaine](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colincaine/32/7211_2.png) [@ColinCaine](https://discourse.julialang.org/u/ColinCaine)\
**Post date:** [May 26, 2020, 2:05pm UTC](https://discourse.julialang.org/t/how-to-safely-cast-c-union-types-use-pointer-from-objref/40162/6 "2020-05-26T14:05:44Z")

</div>

@yuyichao

Thanks for the clarifications.

Making a Ref from the event later does seem to work fine, but I’ll change it as you suggest.

> Back to the code, doing `pointer_from_objref` on the `Ref` is OK, though you do need to `GC.@preserve` the input argument to `pointer_from_objref` for as long as you use the returnend pointer to access the underlaying memory.

To be totally clear, I’m safe to not preserve the `event` once `unsafe_load` has returned?

@Gnimuc

Thanks for those links. Yes, I know about Jonathan’s wrapper already, I started work on my own wrapper to address some minor issues in their one. Maybe my experiment and Jonathan’s project will merge at some point.

I’m not sure I want to overload getproperty like that, but, that was something else I was considering and it’s useful to see it done 🙂 Doesn’t it mean that you potentially make a copy of the event for every propery access, though?

Mostly unrelated: I thought that SFML and GLFW didn’t handle input, because both of them leave that off the top-level description. But they do! They consider that to be part of the Window handling. Woops!

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [May 26, 2020, 2:43pm UTC](https://discourse.julialang.org/t/how-to-safely-cast-c-union-types-use-pointer-from-objref/40162/7 "2020-05-26T14:43:20Z")

</div>

> [@ColinCaine](#):
>
> Making a Ref from the event later does seem to work fine, but I’ll change it as you suggest.

As long as you hahvae access to the `Ref` it’ll work. Or if `event` is mutable it is also fine.

> [@ColinCaine](#):
>
> To be totally clear, I’m safe to not preserve the `event` once `unsafe_load` has returned?

Yes.

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [May 26, 2020, 3:42pm UTC](https://discourse.julialang.org/t/how-to-safely-cast-c-union-types-use-pointer-from-objref/40162/8 "2020-05-26T15:42:03Z")

</div>

> [@ColinCaine](#):
>
> I’m not sure I want to overload getproperty like that, but, that was something else I was considering and it’s useful to see it done 🙂 Doesn’t it mean that you potentially make a copy of the event for every propery access, though?

Maybe it’s a good idea to also implement `getproperty` methods for `Ref{Event}`:

```julia
@inline function unpack_unionref(::Type{T}, objref::Ref{S}) where {T,S}
    GC.@preserve objref unsafe_load(Ptr{T}(Base.unsafe_convert(Ptr{Cvoid}, objref)))
end

function Base.getproperty(objref::Ref{sfEvent}, sym::Symbol)
    if sym === :type
        return getfield(objref, :type)
    elseif sym === :size
        return unpack_unionref(sfSizeEvent, objref)
  ......
    end
end

```
