解决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
相关产品推荐
相关产品推荐

