对 gdk_pixbuf_save & gdk_pixbuf_new_from_data 的未定义引用

Undefined Reference to gdk_pixbuf_save & gdk_pixbuf_new_from_data

我有以下代码,它是对找到的代码的修改 here. In conjunction with this tutorial here

static void * snapshot_function(void *userdata){
    CustomData *data = (CustomData *) userdata;
    gint width, height;
    GstSample *sample;
    GError *error = NULL;
    GdkPixbuf *pixbuf;
    gint64 duration, position;
    GstStateChangeReturn ret;
    gboolean res;
    GstMapInfo map;

    /* Build pipeline */
    data->pipeline_snapshot = gst_parse_launch(pipeline_description_snapshot, &error);

    if (error) {
        gchar *message =
                g_strdup_printf("Unable to build pipeline: %s", error->message);
        g_clear_error(&error);
        set_ui_message(message, data);
        g_free(message);
        return NULL;
    }

    if (error != NULL) {
        g_print ("could not construct pipeline: %s\n", error->message);
        g_error_free (error);
        exit (-1);
    }

    /* get sink */
    data->snapshot_sink = gst_bin_get_by_name (GST_BIN (data->pipeline_snapshot), "sink");

    /* set to PAUSED to make the first frame arrive in the sink */
    ret = gst_element_set_state (data->pipeline_snapshot, GST_STATE_PAUSED);
    switch (ret) {
        case GST_STATE_CHANGE_FAILURE:
            g_print ("failed to play the file\n");
            exit (-1);
        case GST_STATE_CHANGE_NO_PREROLL:
            /* for live sources, we need to set the pipeline to PLAYING before we can
             * receive a buffer. We don't do that yet */
            g_print ("live sources not supported yet\n");
            exit (-1);
        default:
            break;
    }

    /* This can block for up to 5 seconds. If your machine is really overloaded,
 * it might time out before the pipeline prerolled and we generate an error. A
 * better way is to run a mainloop and catch errors there. */
    ret = gst_element_get_state (data->pipeline_snapshot, NULL, NULL, 5 * GST_SECOND);
    if (ret == GST_STATE_CHANGE_FAILURE) {
        g_print ("failed to play the file\n");
        exit (-1);
    }

    /* get the duration */
    gst_element_query_duration (data->pipeline_snapshot, GST_FORMAT_TIME, &duration);

    if (duration != -1)
        /* we have a duration, seek to 5% */
        position = duration * 5 / 100;
    else
        /* no duration, seek to 1 second, this could EOS */
        position = 1 * GST_SECOND;

    /* seek to the a position in the file. Most files have a black first frame so
     * by seeking to somewhere else we have a bigger chance of getting something
     * more interesting. An optimisation would be to detect black images and then
     * seek a little more */
    gst_element_seek_simple (data->pipeline_snapshot, GST_FORMAT_TIME,
                             GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_FLUSH, position);

    /* get the preroll buffer from appsink, this block untils appsink really
     * prerolls */
    g_signal_emit_by_name (data->snapshot_sink, "pull-preroll", &sample, NULL);
    gst_object_unref (data->snapshot_sink);

    /* if we have a buffer now, convert it to a pixbuf. It's possible that we
     * don't have a buffer because we went EOS right away or had an error. */
    if (sample) {
        GstBuffer *buffer;
        GdkPixbuf *pixbuf;
        GstCaps *caps;
        GstStructure *s;

        /* get the snapshot buffer format now. We set the caps on the appsink so
         * that it can only be an rgb buffer. The only thing we have not specified
         * on the caps is the height, which is dependent on the pixel-aspect-ratio
         * of the source material */
        caps = gst_sample_get_caps (sample);
        if (!caps) {
            g_print ("could not get snapshot format\n");
            exit (-1);
        }
        s = gst_caps_get_structure (caps, 0);

        /* we need to get the final caps on the buffer to get the size */
        res = gst_structure_get_int (s, "width", &width);
        res |= gst_structure_get_int (s, "height", &height);
        if (!res) {
            g_print ("could not get snapshot dimension\n");
            exit (-1);
        }

        /* create pixmap from buffer and save, gstreamer video buffers have a stride
         * that is rounded up to the nearest multiple of 4 */
        buffer = gst_sample_get_buffer (sample);
        gst_buffer_map (buffer, &map, GST_MAP_READ);
        pixbuf = gdk_pixbuf_new_from_data (map.data,GDK_COLORSPACE_RGB, FALSE, 8, width, height, GST_ROUND_UP_4 (width * 3), NULL, NULL);

        /* save the pixbuf */
        gdk_pixbuf_save (pixbuf, "snapshot.png", "png", &error, NULL);
        gst_buffer_unmap (buffer, &map);
    } else {
        g_print ("could not make snapshot");
    }

    /* cleanup and exit */
    gst_element_set_state (data->pipeline_snapshot, GST_STATE_NULL);
    gst_object_unref (data->pipeline_snapshot);

    exit (0);
}

但是,在编译时出现以下链接器错误:

C:/Users/user1/AndroidStudioProjects/Project/app/jni/tutorial-3.c:344: undefined reference to `gdk_pixbuf_new_from_data'

C:/Users/user1/AndroidStudioProjects/Project/app/jni/tutorial-3.c:347: undefined reference to `gdk_pixbuf_save' clang++: error: linker command failed with exit code 1 (use -v to see invocation)

我的文件顶部有 #include <gdk-pixbuf-2.0/gdk-pixbuf/gdk-pixbuf.h>,有人知道我可能做错了什么吗?

您在 linking 时遇到问题,因此您需要查看您的构建脚本,您似乎忘记了 link 库。例如,如果您使用 cmake,它将如下所示:

target_link_libraries(tutorial-3 gdk_pixbuf-2.0)