首页 > 解决方案 > 是否已编译 X11 c 程序,出现未定义的引用错误,需要哪些库?

问题描述

我是 Linux 上的 c 编程新手。我的目标是创建一个高效的程序来监控已安装分区 (parm1) 上的可用空间,并在托盘中放置一个图标来表示它,显示我的名字 (parm2) 和可用空间百分比(计算 parm3 的脚本),每 xxx 秒运行一次该脚本 (parm4) 并在值更改时刷新图标 (图标文件名 parm5)。

对于初学者,我刚刚从这里复制了一个示例 c 程序,我只是想让它按原样编译和运行,以便在托盘中嵌入一个带有图标的程序。

C、Xlib 中的 freedesktop XEmbed 系统托盘客户端代码

我对其进行了调整以合并建议的更改并删除错误,它编译干净,但似乎需要添加库才能创建可执行文件。

我如何找出需要哪些库以及将它们放入的顺序?

/* from: https://stackoverflow.com/questions/45392284/freedesktop-xembed-systray-client-code-in-c-xlib */ 

#include <X11/Xutil.h>
#include <string.h>
#include <unistd.h>

#define MIN(A, B)               ((A) < (B) ? (A) : (B))

/* --------- XEMBED and systray stuff */
#define SYSTEM_TRAY_REQUEST_DOCK   0
#define SYSTEM_TRAY_BEGIN_MESSAGE   1
#define SYSTEM_TRAY_CANCEL_MESSAGE  2

int usleep(useconds_t useconds); //pass in microseconds

static int trapped_error_code = 0;
static int (*old_error_handler) (Display *, XErrorEvent *);

static int
error_handler(Display     *display, XErrorEvent *error) {
    trapped_error_code = error->error_code;
    return 0;
}

void
trap_errors(void) {
    trapped_error_code = 0;
    old_error_handler = XSetErrorHandler(error_handler);
}

int
untrap_errors(void) {
    XSetErrorHandler(old_error_handler);
    return trapped_error_code;
}

void
send_systray_message(Display* dpy, long message, long data1, long data2, long data3) {
    XEvent ev;

    Atom selection_atom = XInternAtom (dpy,"_NET_SYSTEM_TRAY_S0",False);
    Window tray = XGetSelectionOwner (dpy,selection_atom);

    if ( tray != None)
        XSelectInput (dpy,tray,StructureNotifyMask);

    memset(&ev, 0, sizeof(ev));
    ev.xclient.type = ClientMessage;
    ev.xclient.window = tray;
    ev.xclient.message_type = XInternAtom (dpy, "_NET_SYSTEM_TRAY_OPCODE", False );
    ev.xclient.format = 32;
    ev.xclient.data.l[0] = CurrentTime;
    ev.xclient.data.l[1] = message;
    ev.xclient.data.l[2] = data1; // <--- your window is only here
    ev.xclient.data.l[3] = data2;
    ev.xclient.data.l[4] = data3;

    trap_errors();
    XSendEvent(dpy, tray, False, NoEventMask, &ev);
    XSync(dpy, False);
    usleep(10000);
    if (untrap_errors()) {
        /* Handle errors */
    }
}

/* ------------ Regular X stuff */
int
main(int argc, char **argv) {
    int width, height;
    XWindowAttributes wa;
    XEvent ev;
    Display *dpy;
    int screen;
    Window root, win;

    /* init */
    if (!(dpy=XOpenDisplay(NULL)))
        return 1;
    screen = DefaultScreen(dpy);
    root = RootWindow(dpy, screen);
    if(!XGetWindowAttributes(dpy, root, &wa))
        return 1;
    width = height = MIN(wa.width, wa.height);

    /* create window */
    win = XCreateSimpleWindow(dpy, root, 0, 0, width, height, 0, 0, 0xFFFF9900);

    /* call send_systray_messsage */
    send_systray_message(dpy, SYSTEM_TRAY_REQUEST_DOCK, win, 0, 0); // pass win only once

    XMapWindow(dpy, win);

    XSync(dpy, False);

    /* run */
    while(1) {
        while(XPending(dpy)) {
            XNextEvent(dpy, &ev); /* just waiting until we error because window closed */
        }
    }
}
$ gcc xmbed_system_tray.c -o xmbed_system_tray 
/usr/bin/ld: /tmp/ccs2ZnYg.o: in function `trap_errors':
xmbed_system_tray.c:(.text+0x3a): undefined reference to `XSetErrorHandler'
/usr/bin/ld: /tmp/ccs2ZnYg.o: in function `untrap_errors':
xmbed_system_tray.c:(.text+0x57): undefined reference to `XSetErrorHandler'
/usr/bin/ld: /tmp/ccs2ZnYg.o: in function `send_systray_message':
xmbed_system_tray.c:(.text+0xa8): undefined reference to `XInternAtom'
/usr/bin/ld: xmbed_system_tray.c:(.text+0xc2): undefined reference to `XGetSelectionOwner'
/usr/bin/ld: xmbed_system_tray.c:(.text+0xe8): undefined reference to `XSelectInput'
/usr/bin/ld: xmbed_system_tray.c:(.text+0x131): undefined reference to `XInternAtom'
/usr/bin/ld: xmbed_system_tray.c:(.text+0x1ab): undefined reference to `XSendEvent'
/usr/bin/ld: xmbed_system_tray.c:(.text+0x1bf): undefined reference to `XSync'
/usr/bin/ld: /tmp/ccs2ZnYg.o: in function `main':
xmbed_system_tray.c:(.text+0x1f3): undefined reference to `XOpenDisplay'
/usr/bin/ld: xmbed_system_tray.c:(.text+0x24f): undefined reference to `XGetWindowAttributes'
/usr/bin/ld: xmbed_system_tray.c:(.text+0x2b2): undefined reference to `XCreateSimpleWindow'
/usr/bin/ld: xmbed_system_tray.c:(.text+0x2ed): undefined reference to `XMapWindow'
/usr/bin/ld: xmbed_system_tray.c:(.text+0x2fe): undefined reference to `XSync'
/usr/bin/ld: xmbed_system_tray.c:(.text+0x316): undefined reference to `XNextEvent'
/usr/bin/ld: xmbed_system_tray.c:(.text+0x322): undefined reference to `XPending'
collect2: error: ld returned 1 exit status

标签: linuxgccbuildxlib

解决方案


我没有找到任何显示任何内容的视频,但我确实找到了一个网站,在那里他显示了可能的图书馆或位置。因此,我猜测要么我的环境设置错误,所以它找不到它正在寻找的东西,或者它正在寻找的东西没有安装。

http://mech.math.msu.su/~nap/2/GWindow/xintro.html

这没有帮助,但我最终找到了另一个页面:

https://en.wikibooks.org/wiki/X_Window_Programming/Xlib

他们的示例程序有编译指令:

To Compile: gcc -O2 -Wall -o test test.c -L /usr/X11R6/lib -lX11 -lm

所以对于我的我尝试:

gcc -o xmbed_system_tray xmbed_system_tray.c -lX11

通过一次删除一个选项,我发现之前不存在的 -lX11 参数导致了失败,现在可执行文件被创建并运行。

该程序仅消耗约 1 mb 的内存,而我发现能够在托盘中运行程序的其他程序为 25 到 35 mb。


推荐阅读