• 外部语言函数接口

    外部语言函数接口

    Rust 提供了外部语言函数接口(Foreign Function Interface,FFI)到 C 语言库。外部语言函数必须声明在一个 extern 代码块,且该代码块要带有一个包含外部语言库名称的 #[link] 属性。

    1. use std::fmt;
    2. // 此外部代码块链接到 libm 库
    3. #[link(name = "m")]
    4. extern {
    5. // 这是外部语言函数
    6. // 这计算了一个单精度复数的平方根
    7. fn csqrtf(z: Complex) -> Complex;
    8. }
    9. fn main() {
    10. // z = -1 + 0i
    11. let z = Complex { re: -1., im: 0. };
    12. // 调用一个外部语言函数是一种不安全的操作
    13. let z_sqrt = unsafe {
    14. csqrtf(z)
    15. };
    16. println!("the square root of {:?} is {:?}", z, z_sqrt);
    17. }
    18. // 最小化实现单精度复数
    19. #[repr(C)]
    20. #[derive(Clone, Copy)]
    21. struct Complex {
    22. re: f32,
    23. im: f32,
    24. }
    25. impl fmt::Debug for Complex {
    26. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    27. if self.im < 0. {
    28. write!(f, "{}-{}i", self.re, -self.im)
    29. } else {
    30. write!(f, "{}+{}i", self.re, self.im)
    31. }
    32. }
    33. }

    由于调用外部语言函数通常被认为是不安全的,因此围绕它们编写安全的装包代码是相当普遍的。

    1. use std::fmt;
    2. #[link(name = "m")]
    3. extern {
    4. fn ccosf(z: Complex) -> Complex;
    5. }
    6. // 安全装包(原文:safe wrapper)
    7. fn cos(z: Complex) -> Complex {
    8. unsafe { ccosf(z) }
    9. }
    10. fn main() {
    11. // z = 0 + 1i
    12. let z = Complex { re: 0., im: 1. };
    13. println!("cos({:?}) = {:?}", z, cos(z));
    14. }
    15. // 最小化实现单精度复数
    16. #[repr(C)]
    17. #[derive(Clone, Copy)]
    18. struct Complex {
    19. re: f32,
    20. im: f32,
    21. }
    22. impl fmt::Debug for Complex {
    23. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    24. if self.im < 0. {
    25. write!(f, "{}-{}i", self.re, -self.im)
    26. } else {
    27. write!(f, "{}+{}i", self.re, self.im)
    28. }
    29. }
    30. }