Windows RT 和 WinRT 的区别

对 Windows RT 和 WinRT 这两个名词的困惑?

如果你对这两个名称感到困惑,我相信你不会是唯一一个。但是,尽管名称相似,但这两件事确实非常不同。Windows RT 是 Windows 8 系统的特定版本的名称。这类似于您拥有的 Windows 7 的Home版本、Windows 7 的Ultimate版本等一样。我说“相似”是因为它并不完全相同。这些版本的 Windows 7 可能会在您拥有的任何计算机上运行。但是,Windows RT 是专门为具有 ARM 处理器的设备量身定制的。事实上,您可能会说更好的比较应该是“您拥有 Windows Embedded 和 Windows Phone 版本——这种 Windows 的变体可以在台式机和笔记本电脑以外的设备上运行”。但归根结底,需要注意的是 Windows RT 是一个操作系统。

如果您是开发人员,那么您可能会认为 Windows RT 中的“RT”代表运行时。但事实并非如此。我认为 Microsoft 从未宣布过它的确切含义——而且,老实说这也可能并不重要。但遗憾的是,还是有人选择了一个如此令人困惑的名称,例如 WinRT,(正如您仍然期望的那样)其中的 RT 部分确实代表 Runtime

因此,WinRT 是运行时、引擎、API,是开发人员深入了解 Windows 8 系统并为其创建漂亮的、新的 Windows Store 应用程序的方法。当您卷起袖子准备干活时,您打开 Visual Studio 2012 并选择一个 Windows 应用商店的应用程序模板时,您将选择的是使用 WinRT,而不是 Windows RT,也不是 Metro,也不是Modern Apps。(抱歉,Windows 8 的开发人员 API 的命名从头到尾都是一团糟)

如果您想知道是否必须为 ARM 和 x86/64 设备分别开发单独的应用程序?事实证明您不需要。使用您选择的任何技术如 .NET、HTML/JavaScript、Native C 或 C++ 编写的 Windows Store 应用程序将可供使用任一类型处理器的用户下载。

但是,值得注意的是,如果您正在考虑将辛苦赚来的钱花在像 Microsoft Surface 这样的设备上,是无法在 ARM 设备上安装 x86/64 软件的。Surface 设备预装了一些 Microsoft 产品,当然您可以从 Windows 应用商店下载可以在 Windows RT 上运行的其他应用程序,但您不得不将其他旧版应用程序的安装光盘留在架子上的塑料文件夹中闲置了。

 现在您应该了解了它们之间的区别 - Windows RT 和 WinRT 揭开了它的神秘面纱。

原文链接:Confused about Windows RT and WinRT? - Ged Mead's Blog - vbCity - The .NET Developer Community

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

WinRT 的前身:COM

不少人可能对 COM 并没有什么概念,那首先我们来简单说一下 COM 是什么。

例如当你需要提供一些算术的 API 时,你可以定义下面这样一个 interface:

[[uuid(dc58f02e-ceaa-46dc-8fb8-2a1348412421)]]
interface ICalc
{
    HResult Add(int x, int y, int* result);
}

这个 interface 提供了加法的 API,加法 API 传入两个参数,通过指针输出一个参数作为返回值,而 API 自身返回是否执行成功。为了让这个 interface 能够被唯一识别,我们用 GUID(uuid) 给他提供一个 ID。

所有的 COM interface 都自动派生自 IUnknown,其中包含两个用于管理生命周期的引用计数函数 AddRef 和 Release,以及一个用于查询接口的函数 QueryInterface

当我们拿到一个 object 的时候,如果我们想要调用 ICalc 上的方法,很自然我们会想到要把这个 object 先转换到 ICalc 再调用:

object x = ...;
int result;
((ICalc)x).Add(1, 2, &result);

但这样并不安全:你怎么知道这个 object 实现了 ICalc? 于是这里 QueryInterface 就派上用场了,调用它用 GUID 查询接口,成功后会返回给你查询的接口在这个 object 上对应方法表的入口点(等价于强制转换为 ICalc 之后的 object),然后你就能在这个 object 上调用它实现的 ICalc 里的方法了:

object x = ...;
ICalc calcEntry;
if (x.QueryInterface(guid, &calcEntry) == S_OK) {
    int result;
    calcEntry.Add(1, 2, &result);
}

这个时候假设我们 A 包含这个接口的实现,而 B 需要在不知道 A 的实现的情况下调用加法,只需要 A 实现这个 ICalc 的接口并且注册好,那么 B 只需要调用 QueryInterface 就能把 A 传过来的 object 变成 ICalc 然后调用了。

更进一步,我们的 A 有个类型实现了 IClassFactory,里面有个函数 CreateInstance 用来根据 GUID 来创建 object,这样我们在 B 里可以首先从 A 拿到 IClassFactory 的 object,然后直接用 ICalc 的 GUID 来调用它,就能创建一个对应 object 返回给我们来用了。

Windows 贴心的提供了一个系统 API CoGetClassObject,就是用来完成从获取 IClassFactory 到创建对象整个流程的,我们在 B 里简单调用 CoGetClassObject 这个函数,就能做到凭空产生我们想要的 object。

而 A 只需要把自己的 IClassFactory 注册到进程内(如果 A 和 B 在同一个进程里的话)或者系统里(如果 A 是一个独立进程的话)就可以了,这样系统就能知道从哪里去获取这个 IClassFactory。只不过进程内的情况是通过调用 A 暴露的 DllGetClassObject 函数,而不是 CoGetClassObject

如此一来,无论 A 在哪里(进程内或者进程外),只要注册了,B 就能直接用 GUID 创建一个 ICalc 拿来用,进程内调用和进程间调用的差异被 COM 彻底抹除了。

为了沟通 A 和 B,我们用一个叫做 idl 的语言描述接口,编译后会生成一个 tlb 文件来描述类型信息,这个类型信息就能让系统知道你都定义了哪些东西。

COM 得益于其结构化和兼容性的设计,既不像字符串作为交互格式时导致处理容易出现问题,又能在保留兼容性的同时随意扩展已有类型,在 Windows 甚至是 macOS 上都被大量的使用(是的你没有看错,macOS 里也有大量的 COM 接口),但是 COM 也有自身的局限性和难用之处:

  1. 类型定义全靠 GUID,一个 GUID 就是一个类型,没有文档的时候你根本不知道这个 GUID 到底是什么类型
  2. 注册独立进程的 COM 组件要往系统注册表里面写配置,需要管理员身份
  3. 不支持异步,非常不现代

其中第 2 点伴随着 Windows 8 引入 appx 包的概念,已经可以做到在程序包内部注册 COM 组件而不需要写到注册表里,到今天已经不是什么问题。但是 1 和 3 还是没有解决。
原文链接:WinRT: 可能是 Windows 上最好用的 Native ABI 和远程调用方案 - hez2010 - 博客园

posted on 2025-03-02 20:31  喝咖啡就蒜瓣儿  阅读(289)  评论(0)    收藏  举报

导航