C++

將富有 REST 的服務帶給 C++ 開發人員

包業 Poduri

下載代碼示例

在這篇文章我會展示如何使用 c + + 其餘 SDK 生成一個簡單的基於 Windows 的用戶端應用程式,將檔上載到 Dropbox,,同時支援 OAuth 的標準 c + + 類。

連接設備的世界越來越多地進入異構混合物的本機應用程式、 Web 應用程式和 Web 網站的所有連接到雲-和非--基於雲服務的混合。 這些應用程式共用和消耗資料通過此混雜的設備和服務,並為最終使用者提供豐富、 身臨其境的體驗。這些使用者越來越多地使用其個人設備 (智慧手機、 平板電腦、 Pc 和其他類似的設備) 上安裝的應用程式。 開發人員的任務是創建在那些應用程式,以便分享、 組織和查看資料的無縫體驗 — — 和喜悅的使用者。

應用程式是以多種程式設計語言編寫的。 一些,如 PHP、 C# 和JAVA,則由預設啟用 Web 和可能滿足一些常見的方案分享和消費資料。 在其他情況下,可能會利用專門的圖書館,執行伺服器端計算、 處理和分析,並將回應返回到用戶端應用程式。

在他的論文,"歡迎您到叢林"(bit.ly/uhfrzH)、 草本薩特毫不含糊地描述了主流移動到彈性、 分散式運算作為自然的演進,同樣的規模和性能趨勢,有驅動的多核和異構計算納入主流。

C + + 時跨平臺的代碼共用和性能的設計考慮的首選的程式設計語言。 當說到雲計算時,雖然,c + + 看似不會送上充分發揮其潛力。 引此明顯失敗的主要原因之一是圖書館的缺乏的跨平臺、 高性能、 高效可擴展,使 c + + 開發人員要到雲環境中無縫地集成現有的 C 和 c + + 代碼。

C + + 其餘 SDK (bit.ly/VI67I5) 是微軟首次進軍使移到雲環境的本機代碼。 它的目的是為開發人員提供的工具和 Api,解決日常問題的本機代碼遷移到雲中。 初始版本是用戶端、 跨平臺的圖書館訪問其他服務。 目標是使 c + + 其餘 SDK 可以解鎖在雲計算中的本機代碼的真正潛力的真正的跨平臺圖書館。 C + + 其餘 SDK 可以建設更專門的庫,如那些支援創作,Windows Azure 服務的基礎,它將使輕量化、 高性能的 Web 服務,在可擕式的 c + + 代碼,而不需要額外的框架或運行時部署基於雲計算的虛擬機器 (Vm) 中寫。

為什麼選擇 c + + 其餘 SDK?

用於訪問 REST 服務,c + + 開發人員可以生成抽象 WinINet 或 Windows 上 WinHTTP 的 C 樣式 Api 和類似的 Api 在其他平臺上。 鑒於這種選項,呼籲立即回答的一個問題是:為什麼開發商應該選擇 c + + 其餘 SDK?

C + + 其餘 SDK 設計和從地面使用現代 c + + 來寫。 功能包括:

  • 用於訪問基於 REST 的服務,從Windows Vista、 Windows 7、 Windows 8、 Windows 應用商店的應用程式,通過提供非同步綁定到 HTTP,JSON,XML,Uri,Linux 上的本機代碼支援,等等。
  • 在 Windows 應用商店的應用程式允許的 SDK 消費Visual Studio擴展 SDK。
  • 撰寫的非同步作業一致且功能強大的程式設計模型基於標準 C + + 11 的功能。
  • 執行非同步流和可用於讀取和寫入檔/設備流的流緩衝區。

C + + 其他的用戶端類

C + + 休息是使用現代 c + + 和非同步程式設計模式的前提下建立的。 我與 Dropbox 的實驗,我用的 HTTP_client 類、 任務類和非同步流類。 我將討論每個。

班 HTTP_client web::HTTP 命名空間中的 HTTP_client 類顧名思義,用來設置和維護到 HTTP Web 服務的連接。 如果您創建的 HTTP_client 和到服務終結點的 URI 實例,物件實例可用於使用戶端的請求。 非同步是內置的其餘部分 c + + 庫,所以作為任務由庫返回回應。

任務類任務表示有可能可以完成函數產生說任務已經返回時的操作。 並非所有任務都完成,都運行,也不能保證完成後,按。 每個任務的物件的一個成員函數,is_done,它返回一個布林值。 當該任務已完成運行時,is_done,則返回 true ; 否則,它將返回 false。 一旦任務已完成運行 — — is_done 成員函數所返回的布林值所示 — — 該任務調用 get 函數返回的值從任務。 調用 get 函數的 is_done 函數返回 false 時要當心。 這樣做會阻塞執行緒,並擊敗建築在代碼中的非同步模式的整個目的。

而不是不斷地檢查 is_done,它是更好地使用然後函數。 它依賴于一個處理函數附加到任務,類似于在 JavaScript 擴展 Windows 應用商店的應用程式中的承諾。 它應該易於識別為使用 PPL 任務用於 Windows 運行時 (WinRT) 非同步作業程式設計的開發人員。 傳遞給函數然後處理函數應採取參數類型 T 或 <T> 的任務。 使用的參數類型任務 <T> 贈送一個額外的好處:這是唯一的方法,來捕獲任務操作本身所引發的異常 !

因為在任務完成後才調用然後函數的處理常式,調用 get 函數處理常式裡面是安全和不會阻塞執行緒。

非同步流其他地區 c + + 庫包括一套的讀取和寫入流和流緩衝區作為封裝物件的説明器類。 以下的圖案和優先順序設置在標準 c + + 庫、 流和其他 c + + 中的緩衝區分隔的格式資料的輸入和輸出的讀和寫位元組或集合的位元組數和從一些底層的介質,如 TCP 通訊端、 磁片檔或甚至記憶體緩衝區的關注從關注。 在某種程度上,流在斷開與底層的介質,用於讀取和寫入資料。 在 c + + 其餘流與大的區別是他們支援非同步讀取和寫入操作,不同于標準的 c + + 類,阻塞。 正如與其他 c + + 其餘物件的設計,流類中的非同步方法返回任務 <T> 而不是值。

這在 c + + 休息的底漆,與現在是時間去想,其餘 Dropbox API。 這篇文章的其餘部分,我將討論訪問 Dropbox 其餘 API 使用 c + + 休息要上載的檔從本地電腦運行 Windows 使用者的 Dropbox 資料夾。

Dropbox 其餘 API

Dropbox 使用 OAuth 版本 1 到它的 API 的所有請求進行身份驗證 (bit.ly/ZJLP4o),並要求所有的請求都是通過 SSL。 為支援 OAuth 的標準 c + + 庫的互聯網搜索返回僅 OAuth 庫中,liboauth,並且它要求要麼打開­SSL (bit.ly/BpfcH) 或 Mozilla 網路安全服務 (NSS) (mzl.la/abU77o)。 我想要支援 OAuth,因此規定要建立一個支援身份驗證 Dropbox 羽量級、 跨平臺的類。

好奇的人們,溪英里有偉大的系列從 Win32 訪問 Twitter 的 c + + 中的 OAuth 的職位 (bit.ly/137Ms6y)。 我已經建成後他基本的想法,但重構代碼使用 Dropbox Api,使用 c + + 盡可能多的休息所支援的標準 c + + 類型。 此外,我不想使用 WinINet 或 WinHTTP 執行任何 Web 請求,因為那樣會把我綁到 Windows 平臺只逼我使用 C 樣式的 API。

現在我將討論建立一個簡單的 c + + 類,支援 OAuth 和 Win32 應用程式中使用 c + + 休息,Dropbox 調用並將檔上載到 Dropbox。 在後續的文章中,我會展示如何使用 c + + 休息從 Windows 應用程式商店和上傳檔到 Dropbox。

開始編寫的應用程式可以訪問 Dropbox 之前,我需要用 Dropbox 註冊它。 這是在 Dropbox 軟體主控台門戶 (bit.ly/R14tjq)。 我註冊了一個免費的 Dropbox 帳戶、 登錄到主控台應用程式門戶,點擊"創建應用"按鈕創建一個新的應用程式。

這一進程會要求您選擇應用程式名稱、 應用程式類型和許可權類型。 我輸入"測試",選擇了核心應用程式類型 (請參見圖 1)。 Dropbox 選擇器 (JavaScript 開發人員很有用) 和同步 API (最好為 iOS 和 Android 開發者) 的其他應用程式類型。 最後,我選擇了作為完整的 Dropbox,許可權類型,這給我的閱讀、 寫作和與特定的資料夾中,由"沙箱"App 資料夾許可權類型提供關於 Dropbox 的任何資料夾同步的靈活性。

Choices for Creating a Dropbox App
圖 1 選擇創建 Dropbox App

按一下"創建應用"按鈕後,Dropbox 創建應用程式並提供詳細資訊所需的訪問如應用程式鍵、 app 秘密等等,如圖所示,在圖 2。 我記下這些因為我需要他們執行方案的身份驗證和使用 OAuth 的授權請求。

Choosing Dropbox App Details
圖 2 選擇 Dropbox App 詳細資訊

一個簡單的跨平臺 c + + 類的 OAuth

現在,真正的行動 ! 正如我剛才所說,我想寫跨平臺類,可用於跨 Windows 和 Linux。 其餘 SDK c + + 的當前版本不支援從 linux 系統中製作的 HTTPS 請求。 這是令人失望,而且我聽說 Linux 完全 HTTPS 支援即將推出。 我在這裡討論的 c + + 類應跨 Windows 和 Linux 工作,沒有重大的修改。 為了 Dropbox 的支援基於 OAuth 的身份驗證,我不得不滿足下列主要要求 (見 Dropbox 網站的完整的要求):

  • 應通過 SSL 的所有請求。 這意味著使用 HTTPS 只,與 HTTP。
  • OAuth 需要的請求 Uri 和參數是使用 HMAC SHA1 或 RSA SHA1 加密或純文字,如果請求通過 SSL 進行簽名。

以我的實驗中,我使用純文字簽名運輸,使通過 HTTPS 請求安定了。 建築工程跨 Windows 和 Linux 的 API 加密非常複雜且耗時的和值得稍後詳細的勘探。

一次我安定的要求,它是要生成此類的時間。 我宣佈高級別的命名空間,方便調用的身份驗證和命名 oAuth 裡面的一類。 在命名空間級別,我有幾個常量字串為 URI 的終結點、 應用程式鍵和 app app app 註冊過程中和幾個説明器方法,獲得的秘密聲明中所示圖 3

圖 3 建築 oAuth 類

// Dropbox consumer key and secret
const std::wstring consumerKey = L"Your app key";
const std::wstring consumerSecret = L"Your app secret";
// List of Dropbox authenticate, authorize, request and file upload URIs
const std::wstring DropBoxRequestTokenURI =
  L"https://api.dropbox.com/1/oauth/request_token";
const std::wstring DropBoxAuthorizeURI =
  L"https://www.dropbox.com/1/oauth/authorize";
const std::wstring DropBoxAccessTokenURI =
  L"https://api.dropbox.com/1/oauth/access_token";
const std::wstring DropBoxFileUploadURI =
  L"https://api-content.dropbox.com/1/files_put/dropbox/<your file name here>";
const std::wstring LocalFiletoUpload = L"Your local file goes here";

整個 OAuth 協定支援 oAuth 類的 BuildSignedOAuthParameters 方法中實現。 此方法接受 URI 的端點、 HTTP 方法的類型 (GET、 郵政、 投入和等)、 app 鍵、 app 的秘密、 請求權杖和權杖的秘密,並生成一個簽名,應送交跨 Dropbox 隨每個請求。 Dropbox 將嘗試對其最終使用與 HTTPS 請求傳遞的參數生成的確切的簽名和生成的簽名相匹配。 如果簽名不匹配,則返回一個 HTTP 錯誤代碼。

簽名使用亂數產生的 — — 在 OAuth 術語中稱為 nonce — — 包括請求支援 OAuth 協定版本的簽名類型、 更多的時間戳記。 該方法返回的所有必需的參數,進行排序按名稱和簽名 URL 編碼清單 (見圖 4)。

圖 4 樓簽名

HTTPParameters BuildSignedOAuthParameters( 
  const HTTPParameters& requestParameters,
  const std::wstring& url,
  const std::wstring& httpMethod,
  const HTTPParameters* postParameters,
  const std::wstring& consumerKey,
  const std::wstring& consumerSecret,
  const std::wstring& requestToken = L"",
  const std::wstring& requestTokenSecret = L""
  )
{
  std::wstring timestamp = OAuthCreateTimestamp();
  std::wstring nonce = OAuthCreateNonce();          

  m_oauthParameters[L"oauth_timestamp"] = timestamp;
  m_oauthParameters[L"oauth_nonce"] = nonce;
  m_oauthParameters[L"oauth_version"] = L"1.0";
  m_oauthParameters[L"oauth_signature_method"] = L"PLAINTEXT";
  m_oauthParameters[L"oauth_consumer_key"] = consumerKey;

  // Add the request token if found
  if (!requestToken.empty())
  {
    m_oauthParameters[L"oauth_token"] = requestToken;
  }

            
  // Create a parameter list containing both oauth and original
  // parameters; this will be used to create the parameter signature
  HTTPParameters allParameters = requestParameters;
  if(Compare(httpMethod, L"POST", false) && postParameters)
  {
    allParameters.insert(postParameters->begin(), 
      postParameters->end());
  }
  allParameters.insert(m_oauthParameters.begin(), 
    m_oauthParameters.end());

  // Prepare a signature base, a carefully formatted string containing 
  // all of the necessary information needed to generate a valid signature
  std::wstring normalUrl = OAuthNormalizeUrl(url);
  std::wstring normalizedParameters = 
    OAuthNormalizeRequestParameters(allParameters);

  std::wstring signatureBase = 
    OAuthConcatenateRequestElements(httpMethod, 
    normalUrl, 
    normalizedParameters);

  // Obtain a signature and add it to header requestParameters
  std::wstring signature = OAuthCreateSignature(signatureBase, 
    consumerSecret,
    requestTokenSecret);

  m_oauthParameters[L"oauth_signature"] = UrlEncode(signature);

  return m_oauthParameters;
}

支援 OAuth 讓路,我寫的用戶端代碼訪問關於 Dropbox 的檔。 我創建的四種方法:

  1. oAuthLoginAsync:執行到 Dropbox 使用 app 的金鑰和秘密的登錄。
  2. AuthorizeDropBoxAccess:啟動 Internet Explorer 和 Dropbox app 訪問授權。 此方法是特定于 Windows,啟動 Internet Explorer,不論它是否為預設瀏覽器。
  3. oAuthAcquireTokenAsync:執行操作,以獲得實際的 Dropbox 訪問權杖。
  4. UploadFileToDropBoxAsync:上載到 Dropbox 雲存儲的檔從本地系統。

每個這些操作是由極其方便和無縫使用 c + + 其他的用戶端類。

用戶端程式碼

怎麼不會用戶端代碼使用編寫非同步任務與現代 c + + 匹配反對使用 C 樣式的 API? 它是要找出時間。

與 C 樣式等 WinINet API,我將不得不作出以下的 WinINet API 呼叫,讓我的應用程式工作:

  • 手動生成的 HTTP 要求標頭。
  • 調用 InternetCrackUrl 來解決其餘端點 URL。
  • 打電話給 InternetOpen 和獲得互聯網連接的控制碼。 通常這是作為一個 HINTERNET 實例返回。
  • 一旦有效 HINTERNET 控制碼了,打個電話到 Http­OpenRequest,它返回 HINTERNET 的另一個實例。
  • 下次打電話到 HttpAddRequestHeaders,它返回一個布林值,指示是否已成功添加標頭資訊的 HTTP 要求。
  • 一旦成功完成所有前面的步驟與相應的錯誤處理到位打到 HttpSendRequest,它將實際要求傳送給。
  • 在收到前一個請求的回應,使對 InternetReadFile 的另一個調用來讀取回應流。

請注意所有的以前的 Api C 樣式的 Api 沒有現代 c + + 程式設計的成語如共用的指標、 lambda 和內置的非同步模式的支援。

現在的實際代碼使用 c + + 其餘 SDK。 圖 5 演示的 oAuthLoginAsync 函數,執行登錄操作到 Dropbox 和上載到 Dropbox 的檔從本地系統的 UploadFileToDropBoxAsync 函數。

圖 5 oAuthLoginAsync 函數

HTTPParameters BuildSignedOAuthParameters(
  const HTTPParameters& requestParameters,
  const std::wstring& url,
  const std::wstring& httpMethod,
  const HTTPParameters* postParameters,
  const std::wstring& consumerKey,
  const std::wstring& consumerSecret,
  const std::wstring& requestToken = L"",
  const std::wstring& requestTokenSecret = L""
  )
{
  std::wstring timestamp = OAuthCreateTimestamp();
  std::wstring nonce = OAuthCreateNonce();                                         
  m_oauthParameters[L"oauth_timestamp"] = timestamp;
  m_oauthParameters[L"oauth_nonce"] = nonce;
  m_oauthParameters[L"oauth_version"] = L"1.0";
  m_oauthParameters[L"oauth_signature_method"] = L"PLAINTEXT";
  m_oauthParameters[L"oauth_consumer_key"] = consumerKey;
  // Add the request token if found
  if (!requestToken.empty())
  {
    m_oauthParameters[L"oauth_token"] = requestToken;
  }
  // Create a parameter list containing both oauth and original
  // parameters; this will be used to create the parameter signature
  HTTPParameters allParameters = requestParameters;
  if(Compare(httpMethod, L"POST", false) && postParameters)
  {
    allParameters.insert(postParameters->begin(), 
      postParameters->end());
  }
  allParameters.insert(m_oauthParameters.begin(), 
    m_oauthParameters.end());
  // Prepare a signature base, a carefully formatted string containing
  // all of the necessary information needed to generate a valid signature
  std::wstring normalUrl = OAuthNormalizeUrl(url);
  std::wstring normalizedParameters =
    OAuthNormalizeRequestParameters(allParameters);
  std::wstring signatureBase =
    OAuthConcatenateRequestElements(httpMethod,
    normalUrl,
    normalizedParameters);
  // Obtain a signature and add it to header requestParameters
  std::wstring signature = OAuthCreateSignature(signatureBase,
    consumerSecret,
    requestTokenSecret);
  m_oauthParameters[L"oauth_signature"] = UrlEncode(signature);
  return m_oauthParameters;
}
task<void> oAuthLoginAsync(std::shared_ptr<app_credentials>& creds)
{           
  uri url(DropBoxRequestTokenURI);
  std::shared_ptr<oAuth> oAuthObj = std::make_shared<oAuth>();
  auto signatureParams =
   oAuthObj->CreateOAuthSignedParameters(url.to_string(),
   L"GET",
   NULL,
   consumerKey,
   consumerSecret
   );
  std::wstring sb = oAuthObj->OAuthBuildSignedHeaders(url);
  http_client client(sb);   
  // Make the request and asynchronously process the response
  return client.request(methods::GET)
    .then([&creds](http_response response)
  {                                          
    if(response.status_code() != status_codes::OK)
    {                             
      // Handle error cases ...
return pplx::task_from_result();
    }
    // Perform actions here reading from the response stream ...
// in this example, parse the response body and
    // extract the token and token secret
    istream bodyStream = response.body();
    container_buffer<std::string> inStringBuffer;
    return bodyStream.read_to_end(inStringBuffer)
      .then([inStringBuffer, &creds](pplx::task<size_t> previousTask)
    {
      const std::string &text = inStringBuffer.collection();
      // Convert the response text to a wide-character
      // string and then extract the tokens
      std::wstring_convert
        <std::codecvt_utf8_utf16<wchar_t>, wchar_t> utf16conv;
      std::wostringstream ss;
      std::vector<std::wstring> parts;
      ss << utf16conv.from_bytes(text.c_str()) << std::endl;
      Split(ss.str(), parts, '&', false);
      unsigned pos = parts[1].find('=');
      std::wstring token = parts[1].substr(pos + 1, 16);
      pos = parts[0].find('=');
      std::wstring tokenSecret = parts[0].substr(pos + 1);
      creds->set_Token(token);
      creds->set_TokenSecret(tokenSecret);
    });
  });
}

在 oAuthLoginAsync 函數中,我首先構造一個 URI 實例從終結點登錄 URI 的字串表示形式。 下一步,創建 oAuth 類的實例並調用 CreateOAuthSignedParameters,它生成一張地圖,其中包含所有必要的 OAuth 請求參數的成員函數。 最後,我簽了標頭通過調用 OAuthBuildSignedHeaders 的成員函數。 簽署的標頭是根據 OAuth 規範強制性的。 現在開始的 HTTP 通信。 我只需要創建一個 HTTP_client 的實例和簽名的請求字串傳遞給它。 Dropbox 將使用請求字串和頭資訊和生成相同的嘗試請求在伺服器端的字串匹配它反對什麼我作為 HTTP 要求的一部分發送。 中的字串匹配,如果我能成功返回代碼 ; 否則,出現錯誤。

我開始通信過程通過創建 HTTP_client 類的一個實例,然後調用請求的成員函數。 我指定的 HTTP 方法得到。 當請求方法執行結束後時,它返回一個 HTTP_response 物件,我用來分析和提取的權杖和權杖的秘密,其中存儲在 app_credentials 類的實例。 權杖應該和 API 的所有後續請求發給收存。

所示的 UploadFileToDropBoxAsync 函數圖 6。 它的 oAuthLoginAsync 函數到遵循類似的模式,直到生成簽名的 OAuth 報頭。 一旦我建立的頭資訊,創建一個任務,將檔從本地檔案系統讀取到一個 file_stream 物件,並設置該 file_stream 物件作為 HTTP 要求正文。 我可以創建 HTTP_client 類的一個實例和佈建要求實例,其中包含 file_stream 內容作為正文,然後放置 PUT 請求。 完成後,我得到包含 HTTP_response 可解析的成功或失敗的任務。 真的就這麼簡單。

圖 6 UploadFileToDropBoxAsync 函數

task<void> UploadFileToDropBoxAsync(std::shared_ptr<app_credentials>& creds)
{
  using concurrency::streams::file_stream;
  using concurrency::streams::basic_istream;
  uri url(DropBoxFileUploadURI);
  std::shared_ptr<oAuth> oAuthObj = std::make_shared<oAuth>();
  auto signatureParams =     
    oAuthObj->CreateOAuthSignedParameters(url.to_string(),
    L"PUT",
    NULL,
    consumerKey,
    consumerSecret,
    creds->Token(),
    creds->TokenSecret()
    );
  std::wstring sb = oAuthObj->OAuthBuildSignedHeaders(url);
  return file_stream<unsigned char>::open_istream(LocalFiletoUpload)
    .then([sb, url](pplx::task<basic_istream<unsigned char>> previousTask)
  {
    try
    {
      auto fileStream = previousTask.get();
      // Get the content length, which is used to set the
      // Content-Length property
      fileStream.seek(0, std::ios::end);
      auto length = static_cast<size_t>(fileStream.tell());
      fileStream.seek(0, 0);
      // Make HTTP request with the file stream as the body
      http_request req;                                    
      http_client client(sb);                
      req.set_body(fileStream, length);
      req.set_method(methods::PUT);
      return client.request(req)
        .then([fileStream](pplx::task<http_response> previousTask)
      {
        fileStream.close();
        std::wostringstream ss;
        try
        {
          auto response = previousTask.get();
          auto body = response.body();                  
          ss << L"Server returned returned status code "
            << response.status_code() << L"."
            << std::endl;      
          std::wcout << ss.str();
        }
        catch (const http_exception& e)
        {
          ss << e.what() << std::endl;
             }
        std::wcout << ss.str();
      });
      }                       
      catch (const std::system_error& e)
      {
        std::wostringstream ss;
        ss << e.what() << std::endl;
        std::wcout << ss.str();
        // Return an empty task
        return pplx::task_from_result();
      }
  });
}

使用 C 樣式的 API,用於 Web 通信或走的路線建設支援使用平臺-相比­WinINet 等特定的 Api,使用現代 c + + 編寫的代碼是更簡潔、 易讀和優雅。 事實上,所有的低級執行細節都抽象化圖書館的公共介面。 C + + 其餘 SDK 生成對現代 c + + 的承諾,並採用同樣的設計原則的 rest 風格的通信。 最終的結果是一個極其精心設計和圖案庫使用現代 c + +,使得建立連接的應用程式很容易和無縫的過程。

下一步:Windows 應用程式商店

在這篇文章我已經探討如何構建一個簡單的基於 Windows 的用戶端應用程式使用 c + + 其餘 SDK 將檔上載到 Dropbox。 一路走來,我一直還討論了建立支援 OAuth 的標準 c + + 類。 在後續的文章中,我會展示如何構建 Windows 應用商店 app 使用 c + + 其餘 SDK。 下次見!

包業 Poduri 是在 microsoft Windows 團隊的專案經理。C + + 愛好者和作者的書,"現代 c + + 和 Windows 商店 Apps"(包業 Poduri,2013年),他經常博客 c + + 和 Windows 運行時在 sridharpoduri.com

感謝以下技術專家對本文的審閱: Artur Laksberg (Microsoft)
Artur Laksberg 是在 c + + 其餘 SDK 團隊中工作的高級發展線索。