11个版本

0.2.4 2023年12月24日
0.2.3 2023年12月20日
0.2.0 2023年1月13日
0.1.5 2022年3月21日

FFI中排名第127

Download history 18/week @ 2024-03-28 7/week @ 2024-04-04

每月下载量56

MIT许可证

10KB
155

c_import

这是一个提供c_import宏(同时也有cpp_import宏)的小型proc宏crate,可用于将C头文件导入到你的程序中。它利用了bindgen,因此需要在你的系统中安装bindgen。它也支持no_std模式。

使用方法

在你的Cargo.toml文件中

# Cargo.toml

[depenedencies]
c_import = "0.2"

在你的Rust源文件中

// src/main.rs
use c_import::c_import;

c_import!(
    "<stdio.h>", 
    "<cairo/cairo.h>",
    "--link cairo"
);

fn main() {
    let version = unsafe { cairo_version() };
    println!("{}", version);
}

如果你不使用--link指令,你可以使用Rust构建脚本

// build.rs
fn main() {
    println!("cargo:rustc-link-lib=cairo");
}

使用非系统头文件也是可能的,通过用引号包围头文件路径

// src/main.rs
use c_import::c_import;
c_import!("src/my_header.h");

fn main() {
    let version = unsafe { cairo_version() };
    println!("{}", version);
}

额外的clang参数

你可以将额外的clang参数作为宏的额外参数传递

// src/main.rs
use c_import::c_import;
c_import!(
    "src/my_header.h", 
    "-DMY_DEFINE", 
    "-I/somepath/include"
);

fn main() {
    let version = unsafe { cairo_version() };
    println!("{}", version);
}

类似地,你可以调用像pkg-config这样的工具来检索cflags并将它们传递给bindgen

use c_import::c_import;

c_import!(
    "<cairo.h>", 
    "<stdio.h>",
    "$pkg-config --cflags cairo"
);

fn main() {
    let version = unsafe { cairo_version() };
    println!("{}", version);
}

宏参数

  • 正常参数被认为是头文件。
  • --link开头的参数用于向生成的extern函数插入#[link (name = libname)]属性,这允许链接库而不必显式创建包含println!("cargo:rustc-link-lib=libname");的build.rs文件
  • --开头的参数被认为是bindgen参数。
  • -开头的参数被认为是cflags,如包含路径或定义(分别对应"-I"和"-D")。
  • $开头的参数被认为是shell命令,它们返回cflags,类似于pkg-config。

使用C++头文件(有限制)

// src/main.rs
use c_import::cpp_import;

cpp_import!("<FL/Fl.H>");

fn main() {
    let version = unsafe { Fl::api_version() }; // static method of class Fl
    println!("{}", version);
}
// build.rs
fn main() {
    println!("cargo:rustc-link-lib=fltk");
}

另一个示例展示了如何处理C++命名空间

// src/my_header.hpp
#pragma once

namespace my_namespace {
class MyStruct {
    int version_;
  public:
    MyStruct(int version);
    int version() const;
};
}
// src/main.rs
use c_import::cpp_import;

cpp_import!("src/my_header.hpp");

fn main() {
    let h = unsafe { my_namespace_MyStruct::new(2) };
    println!("{}", unsafe { h.version() });
}

限制

  • 主要是bindgen的限制
    • 使用C++头文件。
    • 使用静态内联函数。

无运行时依赖。