19. rust中进行Windows系统开发

一、前言

作为系统级语言,rust可以很容易的和C++一样进行系统级编程,但实际操作后我相信你会遇到相当多的问题。

比如以本文要介绍的windows系统编程为例,由于windows系统底层使用的C/C++语言,导致其大量api的参数都是指针,而rust作为一门安全性极高的语言,对于指针的操作会有极大的限制。

其次就是字符串的问题,windows系统大量api都使用的宽窄字符集,而rust默认使用的是UTF-8编码,这之间就涉及编码转换的问题。

对编码不了解的可以参考这篇文章:编码

而本文就将针对这些问题展开,让你能快速熟悉在rust中使用win api的基本过程。

二、指针

首先第一个麻烦就是指针,rust中也是存在像C/C++那样的指针的,只不过需要使用as关键字进行显示的强制转换:

image-20240115165444512

在rust中,指针和变量一样分为两种类型,第一种是不可变指针,也就是*const,另一种为可变指针,为*mut,其后再跟实际的指针类型,比如这里为i32类型。

注意这里的可变与不可变针对的都是变量papb指向变量的值,比如pa由于是不可变的,所以你不能更改它所保存的a地址上的值,而pb由于是可变的,那么可以修改它所指向的b地址上的值:

image-20240115170043853

设置指针的值同样是通过*pa这样的形式实现的,但由于指针操作是一件非常不安全的事情,所以你必须要将其包裹在unsafe中才能编译通过。

从上图就能看出两者的区别,因为pa指向的不可变值,所以这里就无法为其赋值,但此时pb却是可以的。

如果你希望修改papb本身的值,也就是指针本身所存储的地址,换一个其它变量的地址,那么只需要像普通变量那样在let后面添加一个mut关键字即可:

let mut pa=&a as *const i32;
pa=&b as *const i32 //此时就能修改其上存储的地址

除了这些基本的,标准库也专门提供了一个指针库,比如在C/C++中最常见的null指针,就可以通过下面的代码获取:

image-20240115170808652

看上去这种写法似乎有些奇怪,但实际上就是两个函数而已,第一个为null函数,也就是获取一个不可变的*const指针,而第二个为null_mut函数,用于获取可变的*mut指针。

只不过由于指针也需要具体的类型,所以这里是通过模板的语法在函数名后面添加::<i32>的方式来指明它的类型为i32

这里需要这样写的因为是我们用不上它们,但在实际写代码过程中,一旦我们用于将其填入某个函数参数中,而函数参数本身已经有类型了,所以即使不写::<>指明类型,rust编译器也能自动推断出其类型。

除此之外,正如前面所说,Windows系统底层使用的C/C++语言实现,所以自然就不可避免的在某些时候需要用到C/C++中的数据类型。

比如最常见的void类型指针,在后面的win api编程中你会大量的遇到,而rust本身是没有void类型的。

不过rust同样提供了库ffi来解决这个问题:

image-20240115171742701

ffi库中包含了所有C/C++中的基本数据类型,可以直接使用。

比如我这里想要获取一个c_void类型的指针,就需要先将其引用类型转换为指针,然后再进一步转换为c_void类型的指针,这里用as连续转换了两次,所以看起来有点长,分开看即可。

三、windows

rust中的指针有了前面的基础基本也就够了,字符串的问题放在后面,这里先来聊聊如何在rust中使用win api。

作者:余识
全部文章:0
会员文章:0
总阅读量:0
c/c++pythonrustJavaScriptwindowslinux