【Rust 实战】Rust与C#交互-生成DLL库

简介: 【Rust 实战】Rust与C#交互-生成DLL库

0x00 开篇(Intro)


Rust的强大之处只有你想不到,没有它做不到。既然是打折取代C++语言的旗号,那么肯定只要C++能做到的,他也可以做到。这篇教程来说一下如何使用Rust来创建一个DLL库,并且从C#来调用它。


0x01 所需软件(Software)


  • CLion
  • Visual Studio 2013

注:CLion可以使用VSCode,甚至是记事本来代替,本教程以CLion为例。Visual Studio 2013以上的版本即可。


0x02 编写Rust库(Coding Rust)


创建项目


首先使用CLion创建一个rust lib


0a2653c851af460fa595bd959398a8f1.png


我们直接点开Cargo.toml,按照如下配置添加。


[lib]
name = "TestDLL" #生成dll的文件名
crate-type = ["cdylib"]

这里是配置这个项目生成一个lib库。其中,name是最终生成的DLL库的名称,可以随便起名,我这里按照C#的命名规则来命名为TestDLL。crate-type设置为cdylib。关于为什么这里是cdylib,第四节会解释原因。


简单函数编写


创建完成后,CLion会自动生成单元测试代码,我们可以先直接注释掉。我们先从简单的写起。题目:编写一个函数,输出hello Rust dLL!。代码如下:

#[no_mangle]
pub extern fn hello() {
    println!("hello Rust DLL!");
}

其中,#[no_mangle]为了编译时函数方法名不会被混淆。extern表示该函数是一个外部函数接口。


编译DLL库


控制台直接输入cargo build --release编译。如下图,可以找到DLL文件的位置。


2d65d23f6d4748949b924e4057485923.png


0x03 编写C#项目(Codding C#)


创建项目


简单创建一个C#控制台项目RustDLLTest,如下图所示。


6de278e6d6694ce5bb08e7e842b7e74b.png


导入DLL库


C#导入DLL库的方式有很多种,但是使用Rust生成的DLL库,只能使用DllImoport来导入。具体原因,第四节给出解释。

class Program
    {
        [DllImport("TestDLL.dll", EntryPoint = "hello", CallingConvention = CallingConvention.Cdecl)]
        public static extern void hello();
        static void Main(string[] args)
        {
            hello();
            Console.ReadLine();
        }
    }

DllImport有三个参数,第一个是dll的路径,由于我将dll放到了和生成exe的目录同目录下(如下图),这里就使用了相对路径。第二个参数是ll的入口点,也就是Rust中的方法名。第三个CallingConvention = CallingConvention.Cdecl表示C调用约定。


8ec4f2997fb246878c34ecd6d122b7c6.png


运行程序


直接运行程序,控制台出现hello Rust DLL!。大功告成。可能有部分小伙伴无法运行成功,会碰到BadImageFormatException。第四节将给出解决办法。


12c3b7f3f8814309a195c64f051d4445.png


0x04 答疑解惑(QA)


什么是cdylib


cdylib,是C Dynamic Library的简写,名为C规范动态库。可以生成被其它语言调用的库,也就是跨语言 FFI 使用。因为几乎所有语言都有遵循 C 规范的 FFI 实现,它会按照平台生成.so.dylib.dll等库。当然crate-type还有其它类型,这里暂不介绍了。


为什么只能使用DllImport导入?


DllImport的是标准的dll,可以是DELPHI、C++等各种语言写的标准dll。如果调用C语言等语言编写的普通dll,那么就要用DllImport,典型的像Windows API函数都是C语言编写的dll所以都要DllImport。项目引入的dll,是.NET的dll,它属于非标准dll,只是一个类库。


为什么会报BadImageFormatException?


34e8d716411043c08c7ffba9fbba23de.png


这是由于架构不同的原因。这是一个坑。现在大部分电脑都是64位的架构,而Rust默认生成与电脑架构相同的类库。但是由于C#创建的程序默认是32位架构,导致运行时报错。有以下两种解决办法:


1、Rust生成x86架构的dll库


编译时指定架构,下面的代码是生成x86结构的dll库。

cargo build --release --target i686-pc-windows-msvc

2、指定C# 程序为64位架构

修改项目Properties中的目标平台为x64。


92ba0822ed0b46e1ae72df8a17d3a45b.png


两种办法都可以,选择其一即可。

相关文章
|
8天前
|
C#
C# 解决引用dll,出现dll不可以使用等问题
C# 解决引用dll,出现dll不可以使用等问题
|
8天前
|
Rust 安全 开发者
Rust之旅:打造并发布你的首个Rust库
本文将引导读者走进Rust的世界,从基础概念讲起,逐步深入到如何创建、测试、打包和发布自己的Rust库。通过实际操作,我们将理解Rust的独特之处,并学会如何分享自己的代码到Rust社区,从而为开源世界做出贡献。
|
8天前
|
存储 JSON Rust
【一起学Rust | 进阶篇 | reqwest库】纯 Rust 编写的 HTTP 客户端——reqwest
【一起学Rust | 进阶篇 | reqwest库】纯 Rust 编写的 HTTP 客户端——reqwest
350 0
|
8天前
|
存储 Rust 自然语言处理
【一起学Rust | 进阶篇 | thesaurus-rs库】Rust 的离线同义词库——thesaurus-rs
【一起学Rust | 进阶篇 | thesaurus-rs库】Rust 的离线同义词库——thesaurus-rs
36 0
|
8天前
|
数据采集 前端开发 数据挖掘
Fizzler库+C#:从微博抓取热点的最简单方法
本文介绍如何使用Fizzler库和C#构建微博热点信息爬虫。通过Fizzler的CSS选择器定位关键信息,提取热点标题和排名,实现微博内容的智能挖掘。示例代码展示单线程和多线程采集方法,并涉及代理IP使用。
Fizzler库+C#:从微博抓取热点的最简单方法
|
8天前
|
Rust 关系型数据库 调度
【一起学Rust | 进阶篇 | Fang库】后台任务处理库——Fang
【一起学Rust | 进阶篇 | Fang库】后台任务处理库——Fang
178 0
|
8天前
|
安全 算法 测试技术
C#编程实战:项目案例分析
【4月更文挑战第20天】本文以电子商务系统为例,探讨C#在实际项目中的应用。通过面向对象编程实现组件抽象和封装,确保代码的可维护性和可扩展性;利用安全性特性保护用户数据;借助数据库操作处理商品信息;通过逻辑控制和算法处理订单;调试工具加速问题解决,展现C#的优势:面向对象、数据库交互、数据安全和开发效率。C#在实际编程中展现出广泛前景。
|
8天前
|
SQL 存储 数据库连接
C#编程与数据库交互的实现
【4月更文挑战第20天】C#与数据库交互是现代软件开发的关键,涉及数据库连接、数据操作和访问方式。使用ADO.NET建立连接,执行SQL实现读取、插入、更新和删除数据。可通过直接SQL或数据访问对象进行操作。注意性能优化,使用连接池,处理异常,确保安全,以提升应用性能和稳定性。
|
8天前
|
XML 缓存 算法
C#非强签名dll搜索顺序
C#非强签名dll搜索顺序
|
8天前
|
算法 安全 C#
C#版开源免费的Bouncy Castle密码库
C#版开源免费的Bouncy Castle密码库