如何阻止xcb_image_get产生核心转储?
我想从屏幕读取像素用于屏幕录制,但遇到了一个“核心转储”错误。
构建
gcc -o test test.c -I"/usr/local/include/libdrm" -ldrm -lxcb -lxcb-image
libdrm以后再说,但我在这里提一下,看看是否会引起任何问题。
test.c
// DRM
// https://github.com/ascent12/drm_doc/blob/master/01_intro/01_intro.md
// https://github.com/ascent12/drm_doc/blob/master/01_intro/src/main.c
#include <xf86drm.h>
#include <xf86drmMode.h>
// XCB
#include <xcb/xcb.h>
#include <xcb/xcb_image.h>
// junk
#include <drm_fourcc.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include <stdint.h>
int main(void){
/* Open the connection to the X server */
xcb_connection_t *c = xcb_connect (NULL, NULL);
printf("%d", xcb_connection_has_error(c)); // returns 0
/* Get the first screen */
const xcb_setup_t *setup = xcb_get_setup (c);
printf("%d", setup->status); // returns 1
xcb_screen_iterator_t iter = xcb_setup_roots_iterator (setup);
xcb_screen_t *screen = iter.data;
printf("%d", screen->root == NULL); // returns 0
/* Create the window */
xcb_window_t window = xcb_generate_id (c);
xcb_create_window (c, /* Connection */
XCB_COPY_FROM_PARENT, /* depth (same as root)*/
window, /* window Id */
screen->root, /* parent window */
0, 0, /* x, y */
150, 150, /* width, height */
10, /* border_width */
XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */
screen->root_visual, /* visual */
0, NULL ); /* masks, not used yet */
xcb_generic_error_t *error = xcb_request_check(c, cook);
if (error) {
printf("AAA"); // "AAA" is NOT returned
}
free(error);
/* Map the window on the screen */
xcb_map_window (c, window);
/* Make sure commands are sent before we pause so that the window gets shown */
xcb_flush (c);
xcb_get_geometry_cookie_t geomCookie = xcb_get_geometry (c, window); // window is a xcb_drawable_t
xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply (c, geomCookie, NULL); // err code last
int _x = geom->x;
int _y = geom->y;
int _width = geom->width;
int _height = geom->height;
printf("\n %d %d %d %d\n", _x, _y, _width, _height); // returns 0 0 150 150
// just some test schtuff
xcb_pixmap_t pix = xcb_generate_id (c);
xcb_void_cookie_t pixcook = xcb_create_pixmap (c,
geom->depth, /* depth of the screen */
pix, /* id of the pixmap */
window,
_width, /* pixel width of the window */
_height ); /* pixel height of the window */
// get image
// 0xffffffff = https://en.wikipedia.org/wiki/4,294,967,295
xcb_map_window(c, screen->root);
xcb_image_t* ximg = xcb_image_get(c, screen->root, 0, 0, screen->width_in_pixels, screen->height_in_pixels, 0xffffffff, XCB_IMAGE_FORMAT_Z_PIXMAP);
printf("%d", ximg->width); // ERR here: Segmentation fault (core dumped) ./test
xcb_image_get_pixel(ximg, 0, 0);
xcb_image_destroy(ximg);
pause (); /* hold client until Ctrl-C */
xcb_disconnect (c);
}
我创建了一个窗口来确认xcb确实在工作。
我似乎找不到关于 xcb_image_get_pixel 与 xcb_image_get 的太多文档,过去我把它们和 xcb_get_image 搞混过。
我还在学习,虽然在别处我也看到过Cairo可能是更好的选择,但我仍然想学习。
注x1:我在Wayland下运行最新的Ubuntu。
注x2:我尝试使用 “screen->root” 代替 “window”,反之亦然。我对测试还不太自信,仍在学习阶段,所以欢迎建议或修改。任何帮助都将不胜感激。
解决方案
好吧,我解决了!只是我还不太明白到底是怎么回事……
我把系统从Ubuntu换成了;
Linux Mint Cinnamon
机器:FUJITSU CLIENT COMPUTING LIMITED ESPRIMO G9010
操作系统 | 内核:Linux Mint 22.3 - Cinnamon 64位 | 6.14.0-37-generic
CPU | 显卡:Intel© Core™ i5-10500T CPU @ 2.30GHz × 6 | Intel Corporation CometLake-S GT2 [UHD Graphics 630]
桌面环境 | 显示服务器:Cinnamon 6.6.4 | X11
构建
# Linkages have to be after object files https://stackoverflow.com/questions/42113237/undefined-reference-when-linking-dynamic-library-in-ubuntu-system
gcc -o test test.c -I"/usr/include/libdrm" -ldrm -lxcb -lxcb-image
sudo apt-get update
sudo apt-cache search libdrm
sudo apt-cache search xcb-image
sudo apt-get install libdrm-dev libxcb-image0-dev libxcb1-dev xcb
这些是我记得的、正在使用的库。
代码
// relevant
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <xcb/xcb.h>
#include <xcb/xcb_image.h>
// irrelevant
#include <drm_fourcc.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include <stdint.h>
int main (void){
/* Open the connection to the X server */
xcb_connection_t *c = xcb_connect (NULL, NULL);
printf("%d", xcb_connection_has_error(c));
/* Get the first screen */
const xcb_setup_t *setup = xcb_get_setup (c);
printf("%d", setup->status);
xcb_screen_iterator_t iter = xcb_setup_roots_iterator (setup);
xcb_screen_t *screen = iter.data;
printf("%d", screen->root == NULL);
// https://en.wikipedia.org/wiki/4,294,967,295
xcb_image_t* ximg = xcb_image_get(c, screen->root, 0, 0, screen->width_in_pixels, screen->height_in_pixels, 0xffffffff, XCB_IMAGE_FORMAT_Z_PIXMAP);
xcb_map_window(c, screen->root);
printf("%d", ximg == NULL);
printf("%d", ximg->width);
uint32_t p = xcb_image_get_pixel(ximg, 0, 0);
printf("\n\n%d", p);
xcb_image_destroy(ximg);
xcb_disconnect (c);
}
希望有人能帮我理解。
我的最佳猜测是它和“pause”以及“xcb_flush (c);”有关——也许移动“xcb_map_window”有帮助?