Rust与C接口交互

Rust 对于与其他编程语言的互操作性有着出色的支持。这意味着:

  • 从其他语言调用 Rust 函数。
  • 从 Rust 调用用其他语言编写的函数。

调用C接口库

以windows下Dll库为例。

C库准备

先通过VS生成一个Dll库,对应的C头文件:

c 复制代码
#ifdef CEXPORTLIB_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
    typedef struct {
        double real;
        double imag;
    }Complex;
    Complex DLL_API add(Complex first, Complex second);
    //Complex DLL_API add(const Complex& first, const Complex& second);
    void DLL_API add_self(Complex& first, const Complex& second);
#ifdef __cplusplus
}
#endif

Rust侧调用

1、build脚本

在Cargo.toml中增加build项:

c 复制代码
[package]
...
build = "build.rs"

在根目录(Cargo.toml同一层)增加build.rs(里面main与main.rs中的main没任何关系)

rust 复制代码
// build.rs
fn main() {
    // println!("cargo::rustc-link-lib=dylib=stdc++"); // This line may be unnecessary for some environment.
    println!("cargo::rustc-link-search=./x64/Debug"); // lib所在目录
}

2、rust中声明C库中的接口与结构

#[repr©]用于向 Rust 编译器指定这个 struct 总是使用和 C 代码相同的规则来组织内部成员的内存布局。

rust 复制代码
// c_handle.rs
#[repr(C)]
#[derive(Debug)]
pub struct Complex {
    pub real: f64,
    pub imag: f64,
}
#[link(name = "c_export_lib", kind = "dylib")]
unsafe extern "C" {
    // 此种方式会转移所有权,调用后first与second都无法再访问
    // pub fn add(first: Complex, second: Complex) -> Complex;
    // 此种方式不会转移所有权
    pub fn add(first: *const Complex, second: *const Complex) -> Complex;
    pub fn add_self(first: *mut Complex, second: *const Complex) -> ();
}

3、rust中调用接口

rust 复制代码
  let a = c_handle::Complex { real: 1.0, imag: 2.0 };
  let b = c_handle::Complex { real: 3.0, imag: 4.0 };
  // let c = unsafe { c_handle::add(a, b) }; // 此种方式后面不能在访问a、b
  let c = unsafe { c_handle::add(&a, &b) };
  println!("{:?} + {:?} = {:?}", a, b, c);  
  let mut d = c_handle::Complex { real: 2.0, imag: 2.0 };
  unsafe {
    c_handle::add_self(&mut d, &b);
  }
  println!("{:?}", d);

导出C兼容接口

生成C兼容的接口库,用于其他语言调用;先生成库工程:cargo new r_export --lib

1、toml配置

修改cargo.toml增加库说明

rust 复制代码
[package]
build = "build.rs"

[lib]
crate-type = ["cdylib"]

[dependencies]

[build-dependencies]
cbindgen = "0.29.0"

2、对外接口

通过pub与extern声明对外兼容接口:

rust 复制代码
#[repr(C)]
pub struct Point {
    pub x: i32,
    pub y: i32,
}
#[unsafe(no_mangle)]
pub extern "C" fn create_point(x: i32, y: i32) -> Point {
    Point { x, y }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn free_point(point: *mut Point) {
    unsafe {
        drop(Box::from_raw(point));
    }
}
#[unsafe(no_mangle)]
pub extern "C" fn hello_world()
{
    println!("hello world");
}

3、编写build.rs

在build脚本中设定导出(如头文件等)

rust 复制代码
// build.rs
use std::env;

fn main() {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

    cbindgen::Builder::new()
        .with_crate(crate_dir)
        .generate()
        .expect("Unable to generate bindings")
        .write_to_file("r_export.h");
}

编译成功后,会自动生成C头文件r_export.h,以及dll库。

相关推荐
知南x44 分钟前
【Ascend C系列课程(高级)】(1) 算子调试+调优
c语言·开发语言
方见华Richard2 小时前
世毫九量子原住民教育理念全书
人工智能·经验分享·交互·原型模式·空间计算
2的n次方_3 小时前
Runtime 执行提交机制:NPU 硬件队列的管理与任务原子化下发
c语言·开发语言
凡人叶枫3 小时前
C++中智能指针详解(Linux实战版)| 彻底解决内存泄漏,新手也能吃透
java·linux·c语言·开发语言·c++·嵌入式开发
微祎_4 小时前
Flutter for OpenHarmony:构建一个 Flutter 重力弹球游戏,2D 物理引擎、手势交互与关卡设计的工程实现
flutter·游戏·交互
暴躁小师兄数据学院4 小时前
【WEB3.0零基础转行笔记】Rust编程篇-第一讲:课程简介
rust·web3·区块链·智能合约
一起养小猫4 小时前
Flutter for OpenHarmony 实战_魔方应用UI设计与交互优化
flutter·ui·交互·harmonyos
凡人叶枫5 小时前
C++中输入、输出和文件操作详解(Linux实战版)| 从基础到项目落地,避坑指南
linux·服务器·c语言·开发语言·c++
傻乐u兔6 小时前
C语言进阶————指针3
c语言·开发语言
CodeSheep程序羊7 小时前
拼多多春节加班工资曝光,没几个敢给这个数的。
java·c语言·开发语言·c++·python·程序人生·职场和发展