使用数组参数从C调用Rust方法

时间:2015-07-06 05:33:03

标签: c rust ffi

我试图从我的C项目中为嵌入式设备调用Rust代码。设备通过UART进行打印,因此我可以看到通话的结果。

以下C和Rust代码按预期工作(我省略了许多编译器Rust代码,以便进行编译)。

C:

uint8_t input[] = {1,2,3};
uint8_t output[] = {4,5,6};
output = func(input, output);
printf("Sum: %d", output[0]);

锈:

#[no_mangle]
pub extern fn func(input: &[u8], dst: &mut[u8]) -> u8 {
  3
}

按预期打印3。但是我坚持要改变传入的数组作为参考:

C:

uint8_t input[] = {1,2,3};
uint8_t output[] = {4,5,6};
func(input, output);
printf("Sum: %d", output[0]);

锈:

#[no_mangle]
pub extern fn func(input: &[u8], dst: &mut[u8]) {
  for i in (0..1) {
      dst[i] = input[i];
  }
}

这是编译,但打印4而不是预期的1.由于某种原因,我无法更改数组的值。有什么想法吗?

编辑:C函数声明分别为:

extern uint8_t func(uint8_t in[64], uint8_t output[64]);
extern void func(uint8_t in[64], uint8_t output[64]);

EDIT2:更新的代码: C:

uint8_t input[64];
uint8_t output[64];
for(uint8_t = 0; i < 64; i++) {
    input[i] = i;
}
func(input, output);
printf("Sum: %d", output[2]);

预计输出2。

2 个答案:

答案 0 :(得分:8)

Rust 中的&[T]与C中的T []T *不一样。您应该永远使用借来的指针与Rust的C代码进行交互。在与C代码交互时,您还应永远,使用[T]str

<强>自从

[T]strdynamically sized types,这意味着它们(任何类型)的所有指针都是常规指针的两倍。这意味着你的C代码传递两个指针,而Rust期望四个。这是一个小小的奇迹,你的第二个例子并没有在你面前爆炸。

Slice Arguments example from the Rust FFI Omnibus几乎就是你想要的。

还有FFI chapter of the Rust Book

编辑:那些C签名也是假的;首先,Rust在任何地方都可以接受的数组大小没有限制,因此我不确定64来自何处。一个模糊的类似Rust类型将是[u8; 64],但即使 仍然仍然不正确,因为C和Rust以不同方式传递固定大小的数组。 / em> C通过引用传递它们,Rust按值传递它们。

编辑2 :假设您正在谈论第二个func,那么Rust翻译就是:

// C ffi signature:
// void copy(uint8_t src[4], uint8_t dst[4]);
#[no_mangle]
pub unsafe extern fn copy(src: *const [u8; 4], dst: *mut [u8; 4]) {
    if src.is_null() { return; }
    if dst.is_null() { return; }

    // Convert to borrowed pointers.
    let src: &[u8; 4] = &*src;
    let dst: &mut [u8; 4] = &mut *dst;

    for (s, d) in src.iter().zip(dst.iter_mut()) {
        *d = *s;
    }
}

#[cfg(test)]
#[test]
fn test_copy() {
    let a = [0, 1, 2, 3];
    let mut b = [0; 4];
    unsafe { copy(&a, &mut b); }
    assert_eq!(b, [0, 1, 2, 3]);
}

答案 1 :(得分:0)

我还在Rust nightly书中找到了很多有用的信息,其中函数&#34; dot_product&#34;基本上完全符合我的要求:https://doc.rust-lang.org/nightly/book/no-stdlib.html