You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决plotters::CairoBackend与GTK的cairo-rs版本兼容错误

问题

使用GTK构建GUI、plotters crate实现绘图时,初始化CairoBackend遇到依赖版本冲突问题:gtk依赖的cairo-rs v0.16.7与plotters-cairo v0.3.2依赖的cairo-rs v0.15.12版本不一致,导致gtk::cairo::Context与plotters_cairo::CairoBackend::new所需的cairo::context::Context类型不兼容,无法正常编译。

用户提供的配置与代码如下:

Cargo.toml配置

[package]
name = "testing3"
version = "0.1.0"
edition = "2021"

[dependencies]
gtk = "0.16.2"
plotters = "0.3.4"
plotters-cairo = "0.3.2"

Rust代码

use gtk::prelude::*;
use plotters::prelude::*;
use gtk::{Application, ApplicationWindow};

fn main() {
    let app = Application::builder().build();
    
    app.connect_activate(build_gui);
    app.run();
}

fn build_gui(app: &Application){
    let win = ApplicationWindow::builder().application(app).default_width(320).default_height(200).title("Test").build();
    let da: gtk::DrawingArea = gtk::DrawingArea::builder().build();
    
    da.connect_draw(move|_, c|{
            let root = plotters_cairo::CairoBackend::new(c, (1024, 768)).unwrap().into_drawing_area();
            gtk::Inhibit(false)
        });
    win.add(&da);
    win.show_all();
}

错误信息

--> src/main.rs:21:49
   |
21 |             let root = plotters_cairo::CairoBackend::new(c, (1024, 768)).unwrap().into_drawing_area();
   |                        --------------------------------- ^ expected struct `cairo::context::Context`, found struct `gtk::cairo::Context`
   |                        |
   |                        arguments to this function are incorrect
   |
   = note: struct `gtk::cairo::Context` and struct `cairo::context::Context` have similar names, but are actually distinct types
note: struct `gtk::cairo::Context` is defined in crate `cairo`
  --> /home/maindesktop/.cargo/registry/src/github.com-1ecc6299db9ec823/cairo-rs-0.16.7/src/context.rs:72:1
   |
72 | pub struct Context(ptr::NonNull<cairo_t>);
   | ^^^^^^^^^^^^^^^^^^
note: struct `cairo::context::Context` is defined in crate `cairo`
  --> /home/maindesktop/.cargo/registry/src/github.com-1ecc6299db9ec823/cairo-rs-0.15.12/src/context.rs:72:1
   |
72 | pub struct Context(ptr::NonNull<cairo_t>);
   | ^^^^^^^^^^^^^^^^^^
   = note: perhaps two different versions of crate `cairo` are being used?
note: associated function defined here
  --> /home/maindesktop/.cargo/registry/src/github.com-1ecc6299db9ec823/plotters-cairo-0.3.2/src/backend.rs:70:12
   |
70 |     pub fn new(context: &'a CairoContext, (w, h): (u32, u32)) -> Result<Self, CairoError> {
   |            ^^^

For more information about this error, try `rustc --explain E0308`.
error: could not compile `testing3` due to previous error


------------------
(program exited with code: 101)
解决方案

1. 统一依赖版本

修改Cargo.toml,强制所有依赖使用与gtk一致的cairo-rs版本,同时升级plotters-cairo到兼容的版本:

[package]
name = "testing3"
version = "0.1.0"
edition = "2021"

[dependencies]
gtk = "0.16.2"
plotters = "0.3.4"
plotters-cairo = "0.3.4" # 与plotters主版本保持一致,适配cairo-rs v0.16.x
cairo = "0.16.7" # 强制使用与gtk匹配的cairo-rs版本

说明:plotters-cairo v0.3.4已适配cairo-rs v0.16.x系列,可与gtk v0.16.2完美兼容。若后续版本出现冲突,可执行cargo tree | grep cairo查看依赖树,定位冲突源。

2. 调整代码适配

修改绘图逻辑,将gtk::cairo::Context转换为统一版本的&cairo::Context,并使用DrawingArea的实际尺寸进行绘图:

use gtk::prelude::*;
use plotters::prelude::*;
use gtk::{Application, ApplicationWindow};
use cairo::Context; // 引入统一版本的Cairo Context

fn main() {
    let app = Application::builder().build();
    
    app.connect_activate(build_gui);
    app.run();
}

fn build_gui(app: &Application){
    let win = ApplicationWindow::builder()
        .application(app)
        .default_width(320)
        .default_height(200)
        .title("Test")
        .build();
    let da: gtk::DrawingArea = gtk::DrawingArea::builder().build();
    
    da.connect_draw(move|da, c|{
        // 将GTK提供的Context转换为统一版本的引用
        let cairo_ctx: &Context = c.as_ref();
        // 获取DrawingArea的实际显示尺寸
        let allocation = da.allocation();
        let (width, height) = (allocation.width() as u32, allocation.height() as u32);
        
        // 初始化CairoBackend
        let root = plotters_cairo::CairoBackend::new(cairo_ctx, (width, height))
            .unwrap()
            .into_drawing_area();
        
        // 示例:绘制简单折线图
        root.fill(&WHITE).unwrap();
        let mut chart = ChartBuilder::on(&root)
            .caption("Test Plot", ("sans-serif", 20).into_font())
            .build_cartesian_2d(0..10, 0..10)
            .unwrap();
        
        chart.configure_mesh().draw().unwrap();
        chart.draw_series(LineSeries::new(
            vec![(0, 0), (5, 5), (10, 0)],
            &RED,
        )).unwrap();
        
        gtk::Inhibit(false)
    });
    win.add(&da);
    win.show_all();
}

3. 依赖版本排查技巧

  • 执行cargo tree | grep cairo查看所有依赖的cairo版本,快速定位冲突项;
  • 查看crates.io上对应crate的版本兼容说明,确认各依赖的版本支持范围;
  • 若需要强制替换依赖版本,可在Cargo.toml中添加[patch.crates-io]字段锁定特定版本。

内容的提问来源于stack exchange,提问作者Galo do Leste

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 10:05:32