Windows runtime 什么是WinRT语言投影?

Windows runtime 什么是WinRT语言投影?,windows-runtime,Windows Runtime,什么是WinRT语言投影以及它们的用途?WinRT中的“投影”是“绑定”的另一个词 WinRT语言投影是支持的每种语言的WinRT绑定 有关更多信息,请查看: 最简单的澄清方法是WinRT中的语言投影是“前端”,而Windows运行时是后端。从三种语言(JS、C#、VB)中的一种编写,它在后端的行为相同 如果你在C++或C语言中编写自己的第三方WINRT组件,你可以从JS、C和VB中使用它,而不必做任何额外的工作。这可能是在编译时(如在C++中)或运行时(如在JavaScript中)或组合时(如

什么是WinRT语言投影以及它们的用途?

WinRT中的“投影”是“绑定”的另一个词

WinRT语言投影是支持的每种语言的WinRT绑定

有关更多信息,请查看:


最简单的澄清方法是WinRT中的语言投影是“前端”,而Windows运行时是后端。从三种语言(JS、C#、VB)中的一种编写,它在后端的行为相同


如果你在C++或C语言中编写自己的第三方WINRT组件,你可以从JS、C和VB中使用它,而不必做任何额外的工作。这可能是在编译时(如在C++中)或运行时(如在JavaScript中)或组合时(如在C#中)。每种语言决定如何最好地呈现WinRT API。大多数时候是直接曝光,但其他时候可能会发生包装或重定向。代表和活动就是一个很好的例子。在C#中,它们显示为C#委托/事件,而不是特定于WinRT的类型。字符串同样被重新映射为本机语言字符串类型,而不是底层的hstring类型。

语言投影是一种以语言友好的方式向您公开Windows运行时API的方法

例如,创建Windows.Globalization.Calendar对象的基本方法是调用:

IInspectable instance;
HRESULT hr = RoActivateInstance(StringToHSTRING("Windows.Globalization.Calendar"), out instance);
if (Failed(hr))
   throw new ComException(hr);

ICalendar calendar;
hr = instance.QueryInterface(IID_ICalendar, out calendar);
if (Failed(hr))
   throw new ComException(hr);
这就是大多数语言所称的“构造函数”。但大多数语言已经有了“创建对象”的语法

如果你在C#你有:

Calendar calendar = new Calendar();
calendar: TCalendar;

calendar := TCalendar.Create;
如果你是帕斯卡语,你有:

Calendar calendar = new Calendar();
calendar: TCalendar;

calendar := TCalendar.Create;
因此,让我们围绕以下内容创建一个类似C#的包装(或投影):

class Calendar : Object
{
   private ICalendar _calendar;

   //constructor
   void Calendar() : base()
   { 
      IInspectable instance;
      HRESULT hr = RoActivateInstance(StringToHSTRING("Windows.Globalization.Calendar"), out instance);
      if (Failed(hr))
         throw new ComException(hr);
      ICalendar calendar;
      hr = instance.QueryInterface(IID_ICalendar, out calendar);
      if (Failed(hr))
         throw new ComException(hr);

      this._calendar = calendar;
   }
}
现在,您可以使用友好的C#样投影:

Calendar cal = new Calendar();
TCalendar = class
private
   FCalendar: ICalendar;
public
   constructor Create;
end;

constructor TCalendar.Create;
var
   instance: IInspectable;
   calendar: ICalendar;
   hr: HRESULT;
begin
   inherited Create;

   hr := RoActivateInstance(StringToHSTRING('Windows.Globalization.Calendar'), {out} instance);
   OleCheck(hr);

   hr = instance.QueryInterface(IID_ICalendar, {out} calendar);
   OleCheck(hr);

   FCalendar := calendar;
end;
构造函数的Pascal版本 假设您正在使用Delphi:您已经有了创建对象的习惯用法。让我们将基础管道转换为友好的Pascal投影:

Calendar cal = new Calendar();
TCalendar = class
private
   FCalendar: ICalendar;
public
   constructor Create;
end;

constructor TCalendar.Create;
var
   instance: IInspectable;
   calendar: ICalendar;
   hr: HRESULT;
begin
   inherited Create;

   hr := RoActivateInstance(StringToHSTRING('Windows.Globalization.Calendar'), {out} instance);
   OleCheck(hr);

   hr = instance.QueryInterface(IID_ICalendar, {out} calendar);
   OleCheck(hr);

   FCalendar := calendar;
end;
现在我们有了德尔菲投影:

Calendar cal = new Calendar();
TCalendar = class
private
   FCalendar: ICalendar;
public
   constructor Create;
end;

constructor TCalendar.Create;
var
   instance: IInspectable;
   calendar: ICalendar;
   hr: HRESULT;
begin
   inherited Create;

   hr := RoActivateInstance(StringToHSTRING('Windows.Globalization.Calendar'), {out} instance);
   OleCheck(hr);

   hr = instance.QueryInterface(IID_ICalendar, {out} calendar);
   OleCheck(hr);

   FCalendar := calendar;
end;
属性(如果有,就使用它们) 在基础
ICalendar
界面中,必须使用以下方法获取和设置属性:

  • 得到一年
  • 设定年份
如果你盲目地将其翻译成C#,你可能会得到:

C#属性方法:

class Calendar : Object
{
   private ICalendar _calendar;

   public int get_Year() { return _calendar.get_Year(); }
   void set_Year(int value) { _calendar.set_Year(value); }
}
TCalendar = class
public
   function get_Year: Integer;
   procedure set_Year(Value: Integer);
end;
Pascal属性方法:

class Calendar : Object
{
   private ICalendar _calendar;

   public int get_Year() { return _calendar.get_Year(); }
   void set_Year(int value) { _calendar.set_Year(value); }
}
TCalendar = class
public
   function get_Year: Integer;
   procedure set_Year(Value: Integer);
end;
但是如果您的语言支持这些属性,您实际上应该将这些属性作为实际的“属性”公开。因此,我们可以使用我们语言固有的属性语法投影这些属性:

C#

class Calendar : Object
{
   private ICalendar _calendar;

   public int Year { 
         get { return _calendar.get_Year(); } 
         set { _calendar.set_Year(value); }
   }
}
TCalendar = class
public
   property Year: Integer read get_Year write set_Year;
end;
type
   TCalendar = class(TObject)
   private
      FCalendar: ICalendar;
      function getDate: TDateTime;
      procedure setDate(Value: TDateTime);
   public
      property Date: TDateTime read getDate write setDate;
   end;

   function TCalendar.GetDate: TDateTime;
   var
      ticks: Int64;
   const
      OA_ZERO_TICKS = Int64(94353120000000000);
      TICKS_PER_DAY = Int64(864000000000);
   begin
      ticks := FCalendar.get_Date().UniversalTime;
      Result := (ticks - OA_ZERO_TICKS) / TICKS_PER_DAY;
   end;

   procedure TCalendar.SetDate(Value: TDateTime);
   var
      ticks: Int64;
   const
      OA_ZERO_TICKS = Int64(94353120000000000);
      TICKS_PER_DAY = Int64(864000000000);
   begin
      ticks := (Value * TICKS_PER_DAY) + OA_ZERO_TICKS;
      FCalendar.set_Date(Round(ticks));
   end;    
帕斯卡

class Calendar : Object
{
   private ICalendar _calendar;

   public int Year { 
         get { return _calendar.get_Year(); } 
         set { _calendar.set_Year(value); }
   }
}
TCalendar = class
public
   property Year: Integer read get_Year write set_Year;
end;
type
   TCalendar = class(TObject)
   private
      FCalendar: ICalendar;
      function getDate: TDateTime;
      procedure setDate(Value: TDateTime);
   public
      property Date: TDateTime read getDate write setDate;
   end;

   function TCalendar.GetDate: TDateTime;
   var
      ticks: Int64;
   const
      OA_ZERO_TICKS = Int64(94353120000000000);
      TICKS_PER_DAY = Int64(864000000000);
   begin
      ticks := FCalendar.get_Date().UniversalTime;
      Result := (ticks - OA_ZERO_TICKS) / TICKS_PER_DAY;
   end;

   procedure TCalendar.SetDate(Value: TDateTime);
   var
      ticks: Int64;
   const
      OA_ZERO_TICKS = Int64(94353120000000000);
      TICKS_PER_DAY = Int64(864000000000);
   begin
      ticks := (Value * TICKS_PER_DAY) + OA_ZERO_TICKS;
      FCalendar.set_Date(Round(ticks));
   end;    
迭代器 我们的想法是创建一个外观和感觉都像您的语言的外观,但在幕后它映射回底层调用。它很深

在WinRT中,所有可枚举的对象都实现

  • IIterable
但在C#中,所有可枚举项都应该从以下内容开始:

  • IEnumerable
因此.NET库有一个内部类,该类修改
IIterable
,并将其公开为
IEnumerable

因此,与其返回一个
可伸缩的
方法,不如:

但在其他语言中,我们已经有了自己的datetime类:

  • C#
    System.DateTimeOffset
  • Javascript
    Date
  • C++
    FILETIME
  • Delphi
    TDateTime
因此,投影将WinRT
DateTime
(一个Int64,是自1601年1月1日以来的100ns间隔数)转换为C#
DateTimeOffset

class Calendar : Object
{
   //System.DateTimeOffset
   DateTimeOffset Date { 
       get { 
          Int64 ticks _calendar.get_Date().UniversalTime(); 
          DateTimeOffset dt = DateTimeOffset.FromFileTime(ticks);
          return dt;
       } 
       set { 
          Int64 ticks = value.ToFileTime();

          DateTime dt = new Windows.Foundation.DateTime();
          dt.UniversalTime = ticks;
          _calendar.set_Date(dt);
       }
}
还有一些类似于德尔福的TDateTime

class Calendar : Object
{
   private ICalendar _calendar;

   public int Year { 
         get { return _calendar.get_Year(); } 
         set { _calendar.set_Year(value); }
   }
}
TCalendar = class
public
   property Year: Integer read get_Year write set_Year;
end;
type
   TCalendar = class(TObject)
   private
      FCalendar: ICalendar;
      function getDate: TDateTime;
      procedure setDate(Value: TDateTime);
   public
      property Date: TDateTime read getDate write setDate;
   end;

   function TCalendar.GetDate: TDateTime;
   var
      ticks: Int64;
   const
      OA_ZERO_TICKS = Int64(94353120000000000);
      TICKS_PER_DAY = Int64(864000000000);
   begin
      ticks := FCalendar.get_Date().UniversalTime;
      Result := (ticks - OA_ZERO_TICKS) / TICKS_PER_DAY;
   end;

   procedure TCalendar.SetDate(Value: TDateTime);
   var
      ticks: Int64;
   const
      OA_ZERO_TICKS = Int64(94353120000000000);
      TICKS_PER_DAY = Int64(864000000000);
   begin
      ticks := (Value * TICKS_PER_DAY) + OA_ZERO_TICKS;
      FCalendar.set_Date(Round(ticks));
   end;    
tl;博士 投影是WinRT周围的一组包装,使其看起来尽可能像您的母语

在C#中,没有人真正编写投影版本;编译器和运行时在幕后完成所有工作,因为它知道如何读取元数据


对于其他语言,翻译后的代码文件可以手动创建,也可以通过导入工具自动创建。

一个细微的区别是,“绑定”可以手动创建,而“投影”始终是自动创建的,即,您不必坐在那里用投影为WinRT手动编写FFI声明,只需使用一次编写的代码,它接受任何WinRT组件,并使用该语言的习惯用法将其暴露给所讨论的语言。