问题标签 [rust-bindgen]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
0 回答
142 浏览

rust - Rust:bindgen 不透明类型和字符串之间的转换

我想在我的 Rust 代码中调用 c++ 代码,所以我使用 bindgen 来生成 FFI 代码。但是,我不知道如何在我的 Rust 代码中将字符串转换为 c++ 中的字符串。

C++ 演示代码:

构建.rs:

FFI代码中定义的std_string是这样的:

如何set_string_value()在我的 Rust 代码中使用函数?它接受 std_string,但我无法将 String 类型转换为 std_string 类型。

提前致谢!

0 投票
1 回答
274 浏览

c++ - 如何将 c_void 发送到另一个线程

我使用 为相机的 C++ 库创建了一个 Rust 包装器,并且 C++ 库中bindgen的相机句柄被定义为typedef void camera_handle移植bindgenpub type camera_hanlde = ::std::os::raw::c_void.

我能够成功连接到相机并拍摄图像,但是我想在一个单独的线程上运行代码来控制相机的温度,本质上是根据我想要的相机的当前温度来改变冷却器的功率与其余代码分开运行。这些调用需要相机句柄,但是当我生成一个新线程时,我不断收到错误消息:

'*mut std::ffi::c_void' cannot be sent between threads safely

在它下面,它提到了the trait 'std::marker::Send' is not implemented for '*mut std::ffi::c_void'.

我怎样才能将它发送到另一个线程,以便我也可以在那里使用这个相机手柄?我对 Rust 有点陌生,并尝试过使用fragilesend_wrapper包装,但都没有成功。

0 投票
1 回答
131 浏览

vector - Vector包含数据但报告长度为0,可以被某些函数访问

我已经为 Rust 中的相机库编写了一个包装器,它命令和操作相机,还使用 ​​bindgen 将图像保存到文件中。一旦我命令开始曝光(基本上是告诉相机拍摄图像),我可以使用以下形式的函数抓取图像:

在 C++ 中,这个函数是:

在 C++ 中,我可以传入表单的缓冲区,imgdata = new unsigned char[length_buffer]该函数将使用来自相机的图像数据填充缓冲区。

在 Rust 中,类似地,我可以传入 Vec: 形式的缓冲区let mut buffer: Vec<u8> = Vec::with_capacity(length_buffer)

目前,我构建代码的方式是有一个主结构,其中包含图像的宽度和高度、相机句柄等设置,包括图像缓冲区。该结构已被初始化为mut

我编写了一个单独的函数,它将主结构作为参数并调用 GetQHYCCDSingleFrame 函数:

调用此函数后,如果我立即检查 main_settings.image_buffer 的长度和容量:

我得到 0 作为长度,buffer_length 作为容量。类似地,打印任何索引,例如main_settings.image_buffer[0]or 1 会导致恐慌退出说len is 0.

这会让我认为GetQHYCCDSingleFrame代码无法正常工作,但是,当我使用fitsioand hdu.write_region(fitsio docs linked here)将 image_buffer 保存到文件时,我使用:

这会将实际图像保存到具有正确大小的文件中,并且是一个非常精细的图像(如果我使用 C++ 程序拍摄时的样子)。但是,当我尝试打印缓冲区时,由于某种原因是空的,但hdu.write_region代码能够以某种方式访问​​数据。

目前,我的(不好的)解决方法是创建另一个向量,从保存的文件中读取数据并保存到缓冲区,然后该缓冲区具有正确数量的元素:

hdu.write_region当函数可以从某个地方访问数据时,为什么我根本无法访问原始缓冲区,为什么它报告长度为 0 ?它究竟从哪里访问数据,我如何才能正确访问它?我对借用和引用有点陌生,所以我相信我在借用/引用缓冲区时可能做错了什么,还是别的什么?

对不起,长篇大论,但细节可能对这里的一切都很重要。谢谢!

0 投票
0 回答
224 浏览

c++ - 当 rust-bindgen 不适用于原始头文件时,为 C++ 库编写包装器的最佳方法是什么?

我正在尝试将 C++ 库移植到 Rust。一个依赖项不是开源的,我只能访问头文件。rust-bindgen并没有从这些头文件生成有效的绑定,在网上搜索了一段时间后,我得出的结论是我需要为上述库编写一个包装器。(这个库的这个头文件来自https://github.com/wpilibsuite/ni-libraries,如果重要的话)。

由于这些问题,我不能在包装器的头文件中包含原始头文件,但我可以在实际的 cpp 文件中包含原始头文件。

要使用类,我只是前向声明了它们,但其中一些标头使用 typedef 和类中的其他字段作为返回类型。似乎没有一种(好的)方法来前向声明或以其他方式使用这些。

我想知道我的方法是否正确,或者是否有更好的方法可以做到这一点,而我对此采取了错误的方式(它可能在自身内部C++rust-bindgen自身内部)。

我当前设置的一个示例:

closed-source.h

wrapper.hpp

wrapper.cpp

0 投票
0 回答
36 浏览

rust - Rust bindgen 和 char 大于 8 位的系统/编译器

我有一个包含字符串常量的 C 头文件

bindgen 将它们翻译成

char(1) 当 C 比8 位更宽时, bindgen 将如何表现。它会生成u16数组吗?

(2) 如果是这样,如何使用翻译后的常量,以便我的 Rust 代码在 char 为 8 位和 16 位的系统上都适用。目前我使用std::ffi::CStr::from_bytes_with_nul()后跟.as_ptr()将这些常量转换为,*const c_char但这不起作用,因为from_bytes_with_nul需要u8切片。

0 投票
1 回答
119 浏览

rust - Rust 程序适用于开发构建,但在发布构建时会出现段错误

我已经为 Rust 中的相机库编写了一个包装器,它命令和操作一个 16 位相机,并且还使用 bindgen 将图像保存到文件中。一旦我命令开始曝光(基本上是告诉相机拍摄图像),我可以使用以下形式的函数抓取图像:

在 C++ 中,这个函数是:

在 C++ 中,我可以传入表单的缓冲区,imgdata = new unsigned char[length_buffer]该函数将使用来自相机的图像数据填充缓冲区。

在 Rust 中,类似地,我可以mut_ptr以 Vec: 的形式传入一个缓冲区let mut buffer: Vec<u16> = vec![0u16; length_buffer]

目前,我构建代码的方式是有一个主结构,其中包含图像的宽度和高度、相机句柄等设置,包括图像缓冲区。该结构已被初始化为mut

当将它传递给GetQHYCCDSingleFrame函数时,我相应地传递它:

当我使用or 构建程序并使用 orcargo build运行cargo build --release时,此代码可以完美运行。程序开始曝光,等待曝光完成,然后“获取”帧并用图像数据正确填充缓冲区。cargo runcargo run --release

但是,最初在编写程序时,我错误地将 GetQHYCCDSingleFrame 函数声明为:

(注意 imgdata 类型从*mut u16到的变化&mut [u16])。

当我将相同的先前缓冲区作为切片而不是指针传递时:

当我使用(dev build with 0 optimizations) 构建cargo build并运行程序时,该程序运行良好。cargo run该函数和调用有效,并且填充了图像缓冲区。cargo build --release但是,当我使用或运行它时,该程序在 GetQHYCCDSingleFrame 处出现段错误cargo run --release (使用 发布构建opt-level = 3)。

使用rust-gdb,段错误是:

我在 Rust 优化方面没有太多经验,也不太了解 Rust 正在做什么优化以导致程序在没有优化的情况下完美运行时出现段错误。我确实明白正确的做法是像现在一样发送 a mut_ptr,一切正常,但回首往事,我想了解为什么以前的错误程序有效但只在开发版本而不是发布版本?是否有可能理解 C++ 代码中的上下文以及那里的要求?还是发生了其他事情?

如果有更多信息可能有助于理解,我也很乐意提供。谢谢!

0 投票
0 回答
49 浏览

rust - 在 rust 构建脚本中链接 C 库

我正在尝试学习如何使用 bindgen。我正在关注文档(https://rust-lang.github.io/rust-bindgen/tutorial-3.html),并且我有以下代码链接到 C 库:

但是当我跑步时cargo build,我得到了note: LINK : fatal error LNK1181: cannot open input file 'vulkan-1.lib'。我做错了什么?

0 投票
1 回答
42 浏览

c++ - 如何在 rust bindgen 中包含 Windows.h?

我正在使用用 c++ 编写的 SimConnect SDK 开始一个新的 MSFS2020 插件。我正在使用 bingen crates 创建与 SDK 的绑定。

我需要包含 Windows.h 才能使绑定起作用,但出现以下错误:

如果我在 Visual Studio 上创建一个简单的 c++ 项目,我可以成功地包含这个头文件,所以它肯定存在,但我没有成功将它添加到我的 rust 版本中。

如何让我的 rust 构建找到此标头并成功绑定 sdk?

笔记:

  1. 我用 Visual Studio 2022 安装了 c++ 工具链
  2. 我安装了 LLVM 工具链并将 LIBCLANG_PATH 添加到我的环境变量中的 LLVM bin 文件夹中
0 投票
2 回答
31 浏览

rust - 尝试通过 cargo fix 更新版本时未找到本地 crate

上下文:
我有一个名为“libmaths”的本地 C 库,然后使用 Bindgen 创建一个“libmaths-sys”包,该包在本地存储在与我的项目相同的目录中。

问题:
我想使用 2021 版 Rust 中的一些功能,目前我的项目是在 2018 年构建的。我正在尝试按照以下说明更新项目:

https://doc.rust-lang.org/cargo/commands/cargo-fix.html

运行 cargo fix --edition。如果您的项目具有多个功能,还可以考虑使用 --all-features 标志。如果您的项目具有由 cfg 属性控制的特定于平台的代码,您可能还希望使用不同的 --target 标志多次运行 cargo fix --edition。

修改 Cargo.toml 以将 edition 字段设置为新版本。

运行您的项目测试以验证一切仍然有效。如果发出新警告,您可能需要考虑再次运行 cargo fix(不带 --edition 标志)以应用编译器给出的任何建议。

要运行 cargo fix --edition,编译器告诉我删除 cargo toml 中的 edition="2018"。在此之后,我收到一个编译错误,指出找不到 libmaths-sys。代码在 2018 年编译和执行正常,但不是没有这个版本标签。

我找不到任何有类似问题的人,这是我的第一个 stackoverflow 问题,所以不确定如何最好地显示我的代码,因为它是一个小项目的上下文。

错误代码

文件结构和项目概述

libmaths包含返回a + b的add.c和返回a - b的subtract.c,头文件add.h指向两个.c文件

bindgen 生成的 Rust 代码通过 libmath-sys 板条箱中的 lib.rs 附加,该板条箱链接到我从树中省略的 OUT DIR 以保存 200 行文件名。