#[SOLVED] Problems with pointer to returned struct

1 messages · Page 1 of 1 (latest)

ancient helm
#

Hi there. I'm having a kinda beginner moment here. I have a proc that creates a struct and during the struct setup I pass a pointer to it to a callback proc in order to register a "listener".
Relevant code:

create_canvas :: proc(state: ^State, width: i32, height: i32) -> Canvas {
    canvas: Canvas = {}
    canvas.width = width
    canvas.height = height
    canvas.surface = wl.wl_compositor_create_surface(state.compositor)

    if canvas.surface == nil {
        fmt.println("Error creating surface")
        return canvas
    }

    egl_window := wl.egl_window_create(canvas.surface, width, height)
    egl_surface := egl.CreateWindowSurface(
        state.egl_render_context.display,
        state.egl_render_context.config,
        egl.NativeWindowType(egl_window),
        nil,
    )

    if egl_surface == egl.NO_SURFACE {
        fmt.println("Error creating window surface")

    }
    if (!egl.MakeCurrent(
               state.egl_render_context.display,
               egl_surface,
               egl_surface,
               state.egl_render_context.ctx,
           )) {
        fmt.println("Error making current!")
    }

    canvas.egl_surface = egl_surface

    canvas.xdg_surface = wl.xdg_wm_base_get_xdg_surface(state.xdg_base, canvas.surface)
    toplevel := wl.xdg_surface_get_toplevel(canvas.xdg_surface)
    wl.xdg_toplevel_set_title(toplevel, "Odin Wayland")
    fmt.println("Canvas", canvas)
    wl.xdg_surface_add_listener(canvas.xdg_surface, &surface_listener, &canvas)

    return canvas
}

On the call to xdg_surface_add_listener() it's where I pass the canvas pointer. After that the idea would be to return the finished struct.
Problem: the struct pointer get to the callback with all the data corrupted. The argument is a rawptr that I then cast(^Canvas)
If I comment that line and do the exact same thing in the main loop, no issues.
Lost here, feeling i'm missing something important (potentially really basic)

#

The listerner code is

surface_listener := wl.xdg_surface_listener {
    configure = surface_configure,
}

surface_configure :: proc "c" (data: rawptr, surface: ^wl.xdg_surface, serial: c.uint32_t) {
    context = runtime.default_context()
    fmt.println("surface_configure")
    canvas := cast(^Canvas)data
    fmt.println(canvas)

    wl.xdg_surface_ack_configure(surface, serial)
    wl.wl_surface_damage(canvas.surface, 0, 0, c.INT32_MAX, c.INT32_MAX)
    wl.wl_surface_commit(canvas.surface)

}
wise compass
#

The pointer you are passing is to a location the stack.

#

Its not the location of the canvas struct after it is returned from the proc.

ancient helm
#

I suspected that would be something like that, happy I was not far off

wise compass
#

I don't know your use case, but some options are to either pass in the storage for the canvas proc(canvas: ^Canvas) or new(Canvas, allocator) it.

ancient helm
#

this is written this way in order to comply with the odin bindings that I wrote (which follow the original libwayland code and are suboptimal), so the listener must have this signature.

#

allocators, got it. I didn't really understand the 'storage for the canvas' bit tough

wise compass
#

create_canvas :: proc(state: ^State, width: i32, height: i32) -> Canvas will return the contents of the canvas and copy the bytes to wherever it is returned. Those bytes are not at the same address as you store wl.xdg_surface_add_listener(canvas.xdg_surface, &surface_listener, &canvas). Right?

So if you change it to this, you already have the address of the canvas struct from somewhere else outside the call.

create_canvas :: proc(canvas: ^Canvas, state: ^State, width: i32, height: i32)
#

Or if you want allocation create_canvas :: proc(state: ^State, width: i32, height: i32, allocator := context.allocator) -> ^Canvas

ancient helm
#

dude, you're awesome. Really clear and happy to report that it's working. I had the same issue down the line and it's already fixed.

#

I went with allocation btw, for the use case seems clearer to me

wise compass
#

Cool 🙂 just remember then you may need to also free the allocation at some point in time, depending on the app structure

ancient helm
#

Thanks a bunch, I spent the last 2 night sessions around this thing

ancient helm