Что может быть причиной "GLib-GObject-CRITICAL" при вызове pango_cairo_font_map_get_default () в libpango? - PullRequest
0 голосов
/ 25 сентября 2018

Это концептуальный вопрос относительно gtk/glib/libpango/libcairo.Давайте прямо к проблеме.

Я обертываю старую библиотеку C в Go, написанную бывшим коллегой, где-то в коде C вызывается pango_cairo_font_map_get_default(), чтобы получить значение по умолчанию font_map.by libpango.

Обтекание происходит в основном из домена Go, входящего в домен C (интерфейс сторонней функции), а сторона C с помощью pthread создает поток, в конце концов, вызывает pango_cairo_font_map_get_default.

Первоначально, все работает отлично на чистой стороне C.После упаковки код C застрял в вызове pango_cairo_font_map_get_default()

printf("before call");
font_map = pango_cairo_font_map_get_default();
printf("after call");

Ожидаемые выходы:

before call
after call

Фактические выходы:

before call
(process:1): GLib-GObject-WARNING **: cannot register existing type 'PangoFontMap'

(process:1): GLib-CRITICAL **: g_once_init_leave: assertion 'result != 0' failed

(process:1): GLib-GObject-CRITICAL **: g_type_register_static: assertion 'parent_type > 0' failed

(process:1): GLib-CRITICAL **: g_once_init_leave: assertion 'result != 0' failed

(process:1): GLib-GObject-CRITICAL **: g_type_register_static: assertion 'parent_type > 0' failed

(process:1): GLib-GObject-WARNING **: cannot register existing type 'PangoCairoFontMap'

Моя собственная симуляция (сторона C в основном объясняет, как мой бывший коллега делал с libpango), демо работает нормально, без предупреждений и без критических выходов:

package main

/*
#cgo CFLAGS: -I/usr/local/include/pango-1.0
#cgo CFLAGS: -I/usr/local/include/glib-2.0
#cgo CFLAGS: -I/usr/local/include/cairo
#cgo LDFLAGS: -L/usr/local/lib -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lglib-2.0
#include <pango/pangocairo.h>
#include <stdio.h>
#include <pthread.h>
void hello() {
    printf("threa id: %li\n", (unsigned long int)pthread_self());
    PangoFontMap* font_map = pango_cairo_font_map_get_default();
    PangoFontDescription* font_desc = pango_font_description_new();
    pango_font_description_set_family(font_desc, "monospace");
    pango_font_description_set_weight(font_desc, PANGO_WEIGHT_NORMAL);
    pango_font_description_set_size(font_desc, 20 * PANGO_SCALE * 700 / 96);
    PangoContext* context = pango_font_map_create_context(font_map);
    PangoFont* font = pango_font_map_load_font(font_map, context, font_desc);
    PangoFontMetrics* metrics = pango_font_get_metrics(font, NULL);
    int width = pango_font_metrics_get_approximate_digit_width(metrics) / PANGO_SCALE;
    int height = (pango_font_metrics_get_descent(metrics)
                    + pango_font_metrics_get_ascent(metrics)) / PANGO_SCALE;
    printf("%d, %d\n", width, height);
    cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
    cairo_t* cairo = cairo_create(surface);
    cairo_set_source_rgb(cairo, 155 / 255.0, 155 / 255.0, 155 / 255.0);
    cairo_rectangle(cairo, 0, 0, width, height);
    PangoLayout* layout = pango_cairo_create_layout(cairo);
    pango_layout_set_font_description(layout, font_desc);
    g_object_unref(layout);
    cairo_destroy(cairo);
    cairo_surface_destroy(surface);
}
void* font() {
    hello();
    hello();
    return NULL;
}
void two_threads() {
    pthread_t thread1;
    pthread_create(&thread1, NULL, font, NULL);
    pthread_join(thread1, NULL);
    pthread_t thread2;
    pthread_create(&thread2, NULL, font, NULL);
    pthread_join(thread2, NULL);
}
*/
import "C"
import "sync"

func main() {
    wg := sync.WaitGroup{}
    for i := 0; i < 1; i++ {
        wg.Add(1)
        go func() {
            C.two_threads()
            wg.Done()
        }()
    }
    wg.Wait()
}

TL; DR: мое понимание pango_cairo_font_map_get_default() всегда будет успешным (поточно-ориентированным, потому что он использует 1.40.4 1.el7), и независимо от того, сколько раз (статическая внутренняя переменная внутри pango) код пытается вызвать.

Таким образом, мои вопросыявляются:

  1. в чем может быть причина cannot register existing type / g_once_init_leave: assertion failed?
  2. почему такая ошибка блокирует код?

1 Ответ

0 голосов
/ 26 сентября 2018

Вероятно, проблема связана с конфликтом между тем, что вы делаете в Go и c, из-за двойной регистрации типа и непрозрачности того, что делают друг друга.Попробуйте использовать привязки go для стека gtk, а не создавать свою собственную оболочку.

...