外部语言函数接口

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. }