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

     2023-02-19     73

关键词:

【中文标题】使用数组参数从 C 调用 Rust 方法【英文标题】:Calling Rust method from C with array parameters 【发布时间】:2015-09-23 03:46:23 【问题描述】:

我正在尝试从我的 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。

【问题讨论】:

【参考方案1】:

Rust 中的 &amp;[T] 与 C 中的 T []T * 不同。您应该永远不要使用借来的指针与来自 Rust 的 C 代码。在与 C 代码交互时,您还应该永远不要使用 [T]str

曾经

[T]str 是 dynamically 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 传递固定大小的数组不同。 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]);

【讨论】:

如果 C 通过引用传递这样的数组,那么 Rust 签名将需要使用 *const [uint8_t; 64]*mut [uint8_t; 64] @ChrisMorgan:更大的问题是它们一开始就不是 64 元素数组,但是是的; uint8_t [64] 作为参数的 Rust 等效项是(至少在我测试过的平台上)*mut [u8; 64] 你说得对,那些签名太可怕了。但我想避免在这里为我的平台编译 libc。另外,我总是在编译时知道数组参数的大小,所以,像 *mut [u8; 64] 很好。尝试了 func(input: *mut [u8; 64], dst: *mut [u8; 64] ),但是我不允许索引或改变参数。 @Jambaman:我不明白这些签名与重新编译 libc 有什么关系,或者它会完成什么。我特别关心的是,在您的 C 代码中,您没有传递长度为 64 的数组,这是等待发生的缓冲区溢出。至于不能使用*mut [u8; 64],那是因为取消引用原始指针是不安全的,必须在unsafe 块内完成。同样,根据您在问题中的解释,链接的示例似乎与您想要的最接近。 我在示例中添加了代码来说明我想要做什么。我基本上只是想将输入数组(我在编译时知道其大小为 64)复制到输出(大小也为 64)。【参考方案2】:

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

【讨论】:

如何使用 web_sys 从 Rust 创建一个 JS 字符串数组?

】如何使用web_sys从Rust创建一个JS字符串数组?【英文标题】:HowtocreateaJSarrayofStringsfromRustusingweb_sys?【发布时间】:2020-08-2221:30:15【问题描述】:我正在尝试使用一个WebAPI,它包含一个从Rust接受字符串数组的方法。我正在使用web... 查看详情

从 C 代码中调用具有复杂参数和复杂返回类型的 C++ 函数

】从C代码中调用具有复杂参数和复杂返回类型的C++函数【英文标题】:CallC++functionwithcomplexparametersandcomplexreturntypeoutofCcode【发布时间】:2017-05-1820:06:48【问题描述】:我有一个C++数学库并用Rust编写一个项目。由于不能直接从Rust... 查看详情

rust宏简记-以vec!为例

...一个仅在非test模式下才有用的宏,换言之,test模式可能使用一个其他的宏。这里不展开此问题。#[macro_export]表示这个宏可以在其他的crate中使用。头部标记的剩余两行也不解释。vec!这个宏有三种形式,第一种类似数组的定义方... 查看详情

如何使用 JNI 从 JAVA 调用带有 C++ 参数的函数?

】如何使用JNI从JAVA调用带有C++参数的函数?【英文标题】:HowtocallafunctionwithargumentsinC++fromJAVAusingJNI?【发布时间】:2015-04-1414:08:47【问题描述】:我正在搞这个任务一段时间......我正在尝试从java调用C#DLL方法。我使用this作为教... 查看详情

抓狂!当 Rust 从 C FFI 调用时,没有产生线程

】抓狂!当Rust从CFFI调用时,没有产生线程【英文标题】:Catchingpanic!whenRustcalledfromCFFI,withoutspawningthreads【发布时间】:2015-02-0716:36:50【问题描述】:我正在处理RustwrapperfortheDuktapeJavaScriptinterpreter。在正常用例中,调用堆栈将如... 查看详情

如何使用JNI从C调用JAVA方法

】如何使用JNI从C调用JAVA方法【英文标题】:HowtouseJNItocallJAVAmethodfromC【发布时间】:2013-05-1320:16:54【问题描述】:我想使用JNI(JavaNativeInterface)来调用特定的javasetter方法,将一个short[]缓冲区作为参数传递给它。Java方法实现如下... 查看详情

如何使用参数从另一个方法调用方法

】如何使用参数从另一个方法调用方法【英文标题】:Howtocallamethodfromanothermethodwitharguments【发布时间】:2011-09-2012:09:03【问题描述】:我想从updateButtonPressed方法中调用另一个方法。这是我尝试过的:-(IBAction)updateButtonPressed[selflo... 查看详情

如何从 python 调用带有 Char** 参数和 int* 参数的 C 方法?

】如何从python调用带有Char**参数和int*参数的C方法?【英文标题】:howtocallCmethodswithChar**argumentandint*argumentsfrompython?【发布时间】:2020-09-0909:54:54【问题描述】:这是加载erf_utils_io_D.dll的module.pyscript,其中包含io.c和io.h文件我成功... 查看详情

js数组方法

...看到,Array作为构造函数,行为很不一致。因此,不建议使用它生成新数组,直接使用数组字面量是更好的做法。push/pop/unshift/shift//增加、删除元素(数组的方法,所以使用时应调用数组名.方法名())arr.slice/splice//截取元素arr... 查看详情

如何在 Rust 结构中使用 C 数组 [重复]

】如何在Rust结构中使用C数组[重复]【英文标题】:HowtouseCarrayinaRuststructure[duplicate]【发布时间】:2019-09-0121:15:14【问题描述】:我正在用rust编写一个驱动程序,我有以下C结构,我需要将其转换为Rust中的等价结构:structvfio_irq_set... 查看详情

使用原始数组/指针参数验证 Objective-C 中的方法调用

】使用原始数组/指针参数验证Objective-C中的方法调用【英文标题】:VerifyingmethodcallsinObjective-Cwithprimitivearray/pointerarguments【发布时间】:2013-01-2118:07:54【问题描述】:我正在测试的类中有两种方法:-(NSUInteger)sendBuffer:(uint8_t*)buffer... 查看详情

c语言数组判断是不是有重复元素?

...方法调用这个方法有4个参数,第一个参数是用于判断的数组,第二个参数是判断哪行的数组不与num数值重复,第三个是判断哪列的数组不与num数值重复,第四个是用于对比重复的数字,这个方法其实就是指定行列的元素是否与... 查看详情

使用指针参数 (WCT) 从 C# 调用 C++ 方法

】使用指针参数(WCT)从C#调用C++方法【英文标题】:CallingC++methodfromC#withpointerparameter(WCT)【发布时间】:2015-12-0112:42:43【问题描述】:我不熟悉从C#调用C++方法的概念。假设我想从C#调用一个C++函数GetThreadWaitChain:https://msdn.microsoft.... 查看详情

当参数之一是指针数组时,如何从 C# 调用 C++ DLL

】当参数之一是指针数组时,如何从C#调用C++DLL【英文标题】:HowtocallC++DLLfromC#whenoneoftheparametersisanarrayofpointers【发布时间】:2017-11-2723:32:24【问题描述】:我有一个DLLpinC++,它接受两个参数,类似于C中的main()函数:参数数量,... 查看详情

Rails 3 升级:使用数组作为参数从 js.erb 调用 javascript 函数

】Rails3升级:使用数组作为参数从js.erb调用javascript函数【英文标题】:Rails3upgrade:Calljavascriptfunctionfromjs.erbwithanarrayasparameter【发布时间】:2016-05-2709:34:50【问题描述】:升级旧的Rails应用程序,我想从原型切换到Jquery,使用不显... 查看详情

使用参数从 Python 调用 C/C++ 代码

】使用参数从Python调用C/C++代码【英文标题】:CallingaC/C++codefromPythonwithanargument【发布时间】:2016-12-0122:10:32【问题描述】:我读过类似的帖子,但没有具体的内容。或者也许我的逻辑不正确,请您纠正我。我正在尝试做的事情... 查看详情

从 Swift 调用带有数组指针和 int 指针的 C 函数

...】:我正在创建一个C库和一个包装器,以便在Swift中轻松使用。C函数有两个参数,一个数组指针和一个int指针:intcrgetproclist(structkinfo_proc*proc_list,size 查看详情

如何获取调用方法的参数值?

...道如何获取这些值。这甚至可能吗?如果是,我认为它与使用MethodInfo对象中的MethodBody属性有关 查看详情