Это концептуальный вопрос относительно 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) код пытается вызвать.
Таким образом, мои вопросыявляются:
- в чем может быть причина
cannot register existing type
/ g_once_init_leave: assertion failed
? - почему такая ошибка блокирует код?