dongle19863 2018-09-25 19:05
浏览 180

在libpango中调用pango_cairo_font_map_get_default()时,“ GLib-GObject-CRITICAL”的原因是什么?

This is a concept question regarding gtk/glib/libpango/libcairo. Let's straight to the problem.

I am wrapping an old C library in Go written by a former colleague, somewhere in the C code calls pango_cairo_font_map_get_default() to get a default font_map maintained by libpango.

The wrapping is basically from Go domain entering the C domain (foreign function interface) and C side using pthread creates a thread eventually calls pango_cairo_font_map_get_default.

Originally, everything works fine on the pure C side. After the wrapping, the C code stuck on the calling of pango_cairo_font_map_get_default()

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

The expected outputs are:

before call
after call

The actual outputs are:

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'

My own simulation (The C side basically explains how my former colleague was doing with libpango) demo works fine, no warning and no critical outputs:

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
", (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
", 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: my understanding of pango_cairo_font_map_get_default() will always succeed (thread safe, because it is using 1.40.4 1.el7), and no matter how many times (static internal variable inside pango) the code tries to call.

Thus, my questions are:

  1. what can be a cause of cannot register existing type/g_once_init_leave: assertion failed?
  2. why such an error blocks the code?
  • 写回答

1条回答 默认 最新

  • douzouchang7448 2018-09-26 01:05
    关注

    The problem is likely due to a conflict between what you are doing in Go and c, due to doubly registering the type and being opaque to what each other are doing. Try to use the go bindings for the gtk stack rather than making your own wrapper.

    评论

报告相同问题?

悬赏问题

  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 关于大棚监测的pcb板设计
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用