对 Windows-rs 的 看法
来自:Tony Huang
仔细看了一下winrt的设计,还是很不错的,集微软技术大成。
Windows技术栈中很重要的一个技术是COM。它的作用就是定义了一个语言无关的abi,让不同的语言可以无压力的互相交互。
举个例子,以前我们用VB6的时候可以使用COM调用ActiveX控件,然后到了.Net,还可以在.Net中直接使用COM组件,甚至可以把自己包装成COM组件来提供服务。
然后,我们再来看Windows在应用程序接口方面,和Linux有什么本质的不同。
在Linux中,所有对内核的调用,最终都是syscall,这个实际上是在每个arch上,通过一个syscall的number做的绑定,还是比较简陋的。操作系统只能提供很有限的syscall,其它的要嘛通过第三方库,要嘛通过ioctl里面的魔幻处理来实现。
而Windows完全不同,它的操作系统API是通过动态链接库的形式提供的。典型的就是那3个dll:KERNEL32.dll, USER32.dll, 和 GDI32.dll。那么它具体怎么跟内核交互,或者如何与系统的其它服务协作为应用程序提供这些功能,就是由操作系统的发行版决定的。从用户程序的视角来说,我只是调用了一个函数。如果使用了新的API,但是跑在老的系统上,只是会动态链接错误,找不到指定的symbol就好了。甚至可以通过API动态的检测是否存在某个接口。
而WinRT的技术基础就是基于COM技术,把这个功能变得更加强大了。
首先所有的操作系统组件(甚至你自己的组件),都可以通过COM把接口暴露出来,提供一份winmd文件,描述了你提供的接口。
然后针对不同的语言,微软官方提供了一个工具,依据这个winmd文件自动生成binding。
比如C++/WinRT,就是提供了一个编译器,在编译你自己的程序之前,根据你的依赖和windows sdk中的winmd文件生成c++的header,给你调用。然后运行时再使用COM把具体的dll和接口注入进来。
而windows-rs(Rust for Windows)干的事情是一样的,但是它很巧妙的利用了cargo的 build.rs 机制,在编译时做这个binding的生成工作 (具体参考 readme: https://github.com/microsoft/windows-rs/blob/master/readme.md)。
所以对于微软来说,由于操作系统的abi是语言无关的,通过winmd(从com的idl编译而来)描述的。那么对于新的语言的支持,只需要2个事情:
1. 针对legacy的win32 api做一下手动的binding
2. 针对新的WinRT API写一个对应的binding生成器
理论上来说,只要你用的api范围够小,rust for windows是能支持rust编译器支持的最低版本的windows的。
来自:Tony Huang
仔细看了一下winrt的设计,还是很不错的,集微软技术大成。
Windows技术栈中很重要的一个技术是COM。它的作用就是定义了一个语言无关的abi,让不同的语言可以无压力的互相交互。
举个例子,以前我们用VB6的时候可以使用COM调用ActiveX控件,然后到了.Net,还可以在.Net中直接使用COM组件,甚至可以把自己包装成COM组件来提供服务。
然后,我们再来看Windows在应用程序接口方面,和Linux有什么本质的不同。
在Linux中,所有对内核的调用,最终都是syscall,这个实际上是在每个arch上,通过一个syscall的number做的绑定,还是比较简陋的。操作系统只能提供很有限的syscall,其它的要嘛通过第三方库,要嘛通过ioctl里面的魔幻处理来实现。
而Windows完全不同,它的操作系统API是通过动态链接库的形式提供的。典型的就是那3个dll:KERNEL32.dll, USER32.dll, 和 GDI32.dll。那么它具体怎么跟内核交互,或者如何与系统的其它服务协作为应用程序提供这些功能,就是由操作系统的发行版决定的。从用户程序的视角来说,我只是调用了一个函数。如果使用了新的API,但是跑在老的系统上,只是会动态链接错误,找不到指定的symbol就好了。甚至可以通过API动态的检测是否存在某个接口。
而WinRT的技术基础就是基于COM技术,把这个功能变得更加强大了。
首先所有的操作系统组件(甚至你自己的组件),都可以通过COM把接口暴露出来,提供一份winmd文件,描述了你提供的接口。
然后针对不同的语言,微软官方提供了一个工具,依据这个winmd文件自动生成binding。
比如C++/WinRT,就是提供了一个编译器,在编译你自己的程序之前,根据你的依赖和windows sdk中的winmd文件生成c++的header,给你调用。然后运行时再使用COM把具体的dll和接口注入进来。
而windows-rs(Rust for Windows)干的事情是一样的,但是它很巧妙的利用了cargo的 build.rs 机制,在编译时做这个binding的生成工作 (具体参考 readme: https://github.com/microsoft/windows-rs/blob/master/readme.md)。
所以对于微软来说,由于操作系统的abi是语言无关的,通过winmd(从com的idl编译而来)描述的。那么对于新的语言的支持,只需要2个事情:
1. 针对legacy的win32 api做一下手动的binding
2. 针对新的WinRT API写一个对应的binding生成器
理论上来说,只要你用的api范围够小,rust for windows是能支持rust编译器支持的最低版本的windows的。