g_boxed_free: утверждение 'G_TYPE_IS_BOXED (boxed_type)' не удалось с gtk3 draw_area и сборкой nasm - PullRequest
0 голосов
/ 02 августа 2020

Я сейчас работаю с linux сборкой nasm и gtk3 drawing_area. Я могу успешно показать окно gtk и визуализировать компоненты (окно отображается с правильным заголовком и размером). Однако я не могу ничего визуализировать в моем gtk drawing_area с помощью cairo. Запустив приведенный ниже код, я получаю следующую ошибку:

GLib-GObject-CRITICAL **: 19:10:00.207: g_boxed_free: assertion 'G_TYPE_IS_BOXED (boxed_type)' failed

Я подозреваю, что ошибка заключается в функциях draw_callback, поскольку я не получаю сообщение об ошибке, если я либо оставлю ее, либо вернусь сразу же при запуске функции. По какой-то странной причине я получаю сообщение об ошибке, если возвращаюсь после установки rdi на r14 и rsi на r15. Функция draw_callback подключается к событию рисования, поскольку я могу выполнить код в функции draw_callback. Я получил те же вызовы logi c и gtk, написанные на COBOL & C, чтобы они работали, так что в этом не должно быть ничего плохого. Скорее всего, проблема заключается в моих навыках сборки (или их отсутствии). Я смог отобразить другие компоненты, такие как флажки, с тем же макетом, поэтому это не должно быть проблемой.

;code.asm
    bits 64

    %define   GTK_WINDOW_TOPLEVEL   0
    %define   GTK_WIN_POS_CENTER    1
    %define   FALSE                 0
    %define   TRUE                  1
    extern    gtk_init
    extern    gtk_window_new
    extern    gtk_window_set_position
    extern    gtk_window_set_default_size
    extern    gtk_window_set_title
    extern    gtk_box_new
    extern    gtk_container_add
    extern    gtk_drawing_area_new
    extern    cairo_move_to
    extern    cairo_rectangle
    extern    gtk_style_context_get_color
    extern    gtk_widget_get_style_context
    extern    cairo_show_text
    extern    cairo_fill
    extern    gtk_box_pack_start
    extern    gdk_cairo_set_source_rgba
    extern    gtk_widget_queue_draw
    extern    gtk_container_set_border_width
    extern    gtk_vbox_new
    extern    exit
    extern    gtk_box_pack_start
    extern    g_signal_connect_data
    extern    gtk_widget_show_all
    extern    gtk_main
    extern    gtk_main_quit
    extern    gtk_widget_show

section .bss
    color:      resq    1
    window:     resq    1   ; pointer to the GtkWidget, in this case the window
    drawing_area: resq    1
    vbox:    resq    1
    quit:       resq    1

section .data

    mainwindow:
    .title:     db  "title",0
    
    signal:
    .draw:  db  "draw", 0
    .destroy:   db  "destroy", 0

    height dd 1000
    width dd 1000

section .text
    global _start

_start:

    xor     rsi, rsi                  ; argv
    xor     rdi, rdi                  ; argc
    call    gtk_init

    mov     rdi, GTK_WINDOW_TOPLEVEL
    call    gtk_window_new
    mov     qword[window], rax

    mov     rdi, qword[window]
    mov     rsi, GTK_WIN_POS_CENTER
    call    gtk_window_set_position

    mov     rdi, qword[window]
    mov     rsi, [height]
    mov     rdx, [width]
    call    gtk_window_set_default_size

    mov     rdi, qword[window]
    mov     rsi, mainwindow.title
    call    gtk_window_set_title

    mov rdi, qword[window]
    mov rsi, 2
    call gtk_container_set_border_width

    xor     r9d, r9d                 
    xor     r8d, r8d                
    xor     rcx, rcx                
    mov     rdx, gtk_main_quit      
    mov     rsi, signal.destroy     
    mov     rdi, qword[window]      
    call    g_signal_connect_data

    mov rdi, 0
    mov rsi, 5
    call gtk_vbox_new
    mov qword [vbox], rax

    mov     rdi, qword[window]
    mov     rsi, qword[vbox]
    call    gtk_container_add

    call gtk_drawing_area_new
    mov qword [drawing_area], rax

    call connect_draw

    mov rdi, qword [vbox]
    mov rsi, qword [drawing_area]
    mov rdx, 1
    mov rcx, 1
    mov r8, 0
    call gtk_box_pack_start
    
    mov rdi, qword[drawing_area]
    call gtk_widget_show

    mov rdi, qword[vbox]
    call gtk_widget_show

    mov rdi, qword[window]
    call gtk_widget_show
    
    call    gtk_main

    xor     rdi, rdi
    call    exit

;The graphics part starts here

connect_draw:
    xor     r9d, r9d      
    xor     r8d, r8d          
    xor     rcx, rcx 
    mov     rdi, qword[drawing_area]
    mov     rsi, signal.draw

    ;A gtk window reference
    mov     rdx, draw_callback
    call    g_signal_connect_data 
    ret


draw_callback: ;GBoolean (GtkWidget *widget, cairo_t *cr, gpointer data)
    mov r14, rdi; GtkWidget *widget
    mov r15, rsi ; cairo_t *cr
   
    mov rdi, r15
    mov rsi, 100
    mov rdx, 100
    mov rcx, 100
    mov r8, 100
    call cairo_rectangle ;void cairo_rectangle (cairo_t *cr, double x, double y,double width, double height);
    ;Nothing happens here

    ;Next lines attempt to fill the drawn rectangle
    mov rdi, r14
    call gtk_widget_get_style_context
; GtkStyleContext *
;   gtk_widget_get_style_context (GtkWidget *widget);

    mov rdi, rax
    mov rsi, 0
    mov rdx, color
    call gtk_style_context_get_color 
;void
; gtk_style_context_get_color (GtkStyleContext *context,
;                              GtkStateFlags state,
;                              GdkRGBA *color);

    mov rdi, r15
    mov rsi, color
    call gdk_cairo_set_source_rgba
    ;void
    ;gdk_cairo_set_source_rgba (cairo_t *cr,
    ;                       const GdkRGBA *rgba);

    mov rdi, r15
    call cairo_fill
;void
;   cairo_fill (cairo_t *cr);

;A nice return value
    mov rax, FALSE
    ret

И, наконец, вот как я компилирую, связываю и запускаю код (на всякий случай)

nasm -felf64 -o code.o -l code.lst code.asm
ld -s -m elf_x86_64 code.o -o code -lc --dynamic-linker /lib64/ld-linux-x86-64.so.2 -lgtk-3 -lpthread -lcairo -lgobject-2.0  -lglib-2.0 -lgdk_pixbuf-2.0 -lgdk-3
./code
...