首页 > 其他分享 >在 C 中使用 Rust 函数

在 C 中使用 Rust 函数

时间:2024-07-30 14:18:19浏览次数:9  
标签:derive false 函数 cbindgen 使用 头文件 include Rust

在 C 中使用 Rust 函数主要通过 Rust 构建动态库,然后 C 使用该动态库来实现。
构建动态库

​ 首先要创建一个动态库项目,使用命令 cargo new hello --lib

​ 我们需要指明库类型为动态库,在 Cargo.toml 文件中添加

[lib]
name = "hello"
crate-type = ["cdylib"]

​ 在 lib.rs 中添加一个最简单的函数

#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
    a + b
}

上面的代码是 Keyword extern 中提到的将 Rust 函数导出到 C lib 中的标准做法,根据这篇帖子externextern "C" 实际上没有区别,因为 Rust 默认使用标准 C ABI 的格式导出。

​ 然后运行 cargo build 命令构建后就可以在 target/debug 下面找到 libadd.so 库文件(Linux 平台,其它系统的后缀不一样)。

构建头文件

​ 在 C 语言中编写库时,通常会在头文件(.h)中包含所有的声明,在 .c 文件中包含所有的实现。在使用时,需要在代码中 include 对应的头文件才能找到对应的声明。但是 Rust 构建出的动态库并没有生成任何头文件。

​ 我们可以直接自己写一个头文件,但是更好的做法是使用 cbindgen 工具。这个工具为你的 Rust 项目中公开的 C API 生成 C/C++11 头文件。

​ cbindgen 接受一个 .toml 作为配置文件,这里使用的模板为

# This is a template cbindgen.toml file with all of the default values.
# Some values are commented out because their absence is the real default.
#
# See https://github.com/mozilla/cbindgen/blob/master/docs.md#cbindgentoml
# for detailed documentation of every option here.
language = "C"
############## Options for Wrapping the Contents of the Header #################

# header = "/* Text to put at the beginning of the generated file. Probably a license. */"
# trailer = "/* Text to put at the end of the generated file */"
# include_guard = "my_bindings_h"
# pragma_once = true
# autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
include_version = false
# namespace = "my_namespace"
namespaces = []
using_namespaces = []
sys_includes = []
includes = []
no_includes = false
# cpp_compat = true
after_includes = ""
############################ Code Style Options ################################

braces = "SameLine"
line_length = 100
tab_width = 4
documentation = true
documentation_style = "auto"
documentation_length = "full"
line_endings = "LF" # also "CR", "CRLF", "Native"
############################# Codegen Options ##################################
style = "both"
sort_by = "Name" # default for `fn.sort_by` and `const.sort_by`
usize_is_size_t = true
[defines]
# "target_os = freebsd" = "DEFINE_FREEBSD"
# "feature = serde" = "DEFINE_SERDE"
[export]
include = []
exclude = []
# prefix = "CAPI_"
item_types = []
renaming_overrides_prefixing = false
[export.rename]
[export.body]
[export.mangle]
[fn]
rename_args = "None"
# must_use = "MUST_USE_FUNC"
# deprecated = "DEPRECATED_FUNC"
# deprecated_with_note = "DEPRECATED_FUNC_WITH_NOTE"
# no_return = "NO_RETURN"
# prefix = "START_FUNC"
# postfix = "END_FUNC"
args = "auto"
sort_by = "Name"
[struct]
rename_fields = "None"
# must_use = "MUST_USE_STRUCT"
# deprecated = "DEPRECATED_STRUCT"
# deprecated_with_note = "DEPRECATED_STRUCT_WITH_NOTE"
derive_constructor = false
derive_eq = false
derive_neq = false
derive_lt = false
derive_lte = false
derive_gt = false
derive_gte = false
[enum]
rename_variants = "None"
# must_use = "MUST_USE_ENUM"
# deprecated = "DEPRECATED_ENUM"
# deprecated_with_note = "DEPRECATED_ENUM_WITH_NOTE"
add_sentinel = false
prefix_with_name = false
derive_helper_methods = false
derive_const_casts = false
derive_mut_casts = false
# cast_assert_name = "ASSERT"
derive_tagged_enum_destructor = false
derive_tagged_enum_copy_constructor = false
enum_class = true
private_default_tagged_enum_constructor = false
[const]
allow_static_const = true
allow_constexpr = false
sort_by = "Name"
[macro_expansion]
bitflags = false
############## Options for How Your Rust library Should Be Parsed ##############
[parse]
parse_deps = false
# include = []
exclude = []
clean = false
extra_bindings = []
[parse.expand]
crates = []
all_features = false
default_features = true
features = []

然后使用命令 cbindgen --config cbindgen.toml --crate cdylib --output add.h 就可以生成一个 add.h 头文件,

#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>

int32_t add(int32_t a, int32_t b);

就是 Rust add 函数的等效声明。

​ 接下来的过程就和在 C 中使用动态库的步骤一致了。

标签:derive,false,函数,cbindgen,使用,头文件,include,Rust
From: https://www.cnblogs.com/kaleidopink/p/18332244

相关文章

  • Python:指定与继承一起使用的类方法的返回类型
    我一直在尝试了解如何在Python中指定类方法的返回类型,以便即使对于子类也能正确解释它(例如在我的Sphinx文档中)。假设我有:classParent:@classmethoddefa_class_method(cls)->'Parent':returncls()classChild(Parent):pass什么如......
  • python使用SMTP功能发送邮件
    网页格式发送for_email.html<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title><style>h1{color:brown;}p{margin:5px;color:purple......
  • python之代码简化式(列表、字典生成式,递归函数,迭代器(iter)和生成器(yield)、匿名函数(
    文章目录前言1、列表、字典生成式2、递归函数2.1python中代码的递归深度(扩展)3、拓展:迭代器和生成器3.1迭代器(iter)3.2生成器(yield)4、匿名函数(lambda)4.1map函数4.2reduce函数(较少使用)4.3filter函数前言本文主要讲解一些简化代码格式的一些方法,方便大家更好的......
  • 如何在没有元类冲突的情况下将泛型类型与 PyQt 子类一起使用?
    我已经尝试过使用sip包装类型,并且当使用abc.ABCMeta进行子类化时效果很好。abc.ABC但它不适用于classQABCMeta(wrappertype,ABCMeta):passclassWidgetBase(QWidget,metaclass=QABCMeta):...classInterfaceWidget(WidgetBase,ABC):......
  • Pattern的使用与Matcher正则表达式的使用。
    Pattern的使用在Java中,java.util.regex.Pattern类用于表示正则表达式的编译表示。正则表达式是一种强大的模式匹配工具,它可以用于搜索、替换和解析字符串。以下是一些常见的正则表达式匹配规则:普通字符:大多数字符都是普通字符,它们匹配自身。例如,正则表达式abc将匹配字符串......
  • C++入门基础—(命名空间,输入输出,缺省参数,函数重载)
    目录1.1 C++发展史1.2C++版本更新1.3C++学习参考文档1.4C++的第一个程序2命名空间2.1命名空间的价值2.2namespace的定义1.命名空间中可以定义变量/函数/类型2.命名空间可以嵌套3.多⽂件中可以定义同名namespace,他们会默认合并到⼀起,就像同⼀个namespace⼀......
  • 【Vue3】前端使用JWT令牌技术的实践方案
    目录技术介绍简单介绍:详细介绍:操作流程1.后端在登录响应里返回jwt2.前端将该变量存入浏览器当中3.前端使用jwt请求的时候作为请求头解码令牌内信息技术介绍简单介绍:        JWT令牌是一种用户校验机制,在登录后服务器会返回用户一个JWT令牌(相当于门票),用......
  • 如何使用支持简单类型和属性的字段声明协议?
    (相关但不重复:如何注释可以实现为属性的属性?)我想创建一个Protocol,其中字段可以通过简单类型和财产。例如:classP(Protocol):v:int@dataclassclassFoo(P):v:intclassBar(P):@propertydefv(self)->int:#ERROR......
  • 如何将多个变量分配给 python 函数中的单个参数?
    我正在尝试编写一个程序,如果可能的话,它需要一个三项式并对其进行因式分解。每当用户输入A、B和C时,三项式应该通过Factor(product,summation)函数获取,但我似乎无法弄清楚如何将A和C分配给乘积arg,将B分配给我尝试在函数外部声明不同的变量,product=(a*c)和summati......
  • 在 Windows 上使用 FFmpeg
    在Windows上使用FFmpeg进行各种多媒体操作相对直接,但需要先完成安装。下面是详细的步骤,包括如何安装和使用FFmpeg:1.安装FFmpeg下载FFmpeg:访问FFmpeg官方网站。在Windows部分,点击WindowsbuildsbyBtbN或WindowsbuildsbyZeranoe(如果有可用)。解压FFmpe......