Search code examples
c++winapic++-winrt

co_await expression needs await_ready function


I have a Win32 programm, where I want to add some winRT calls. Among other things I want to open a file without a GUI interface.

I use the async file open call from the StorageFile class, because the next call needs an IStorageFile interface.

#include <roapi.h>
#include <winrt/Windows.Storage.h> 
#include <winrt/Windows.Foundation.h>

void openFile()
{
   using namespace winrt;
   using namespace winrt::Windows::Foundation;
   using namespace winrt::Windows::Storage;

   HRESULT rtn = RoInitialize(RO_INIT_MULTITHREADED); 
   winrt::hstring path{ L"C:\\Users...\\mytextfile.txt"};

   //wait for open the file 
   auto file = co_await StorageFile::GetFileFromPathAsync(path);

   //IStorageFile interface needed  
}

int main()
{
  openFile(); 
  return 0;
}

At the moment, the compiler complains that the co_await expression requires a suitable "await_ready" function and none was found.

I`m not sure if this is the case due to a missing header include or if "co_await" can not be used within a win32 application.

Edit: My visual studio project setup is: - use c++17, add cppwinrt.exe to my include directories, link against windowsapp.lib and use windows sdk version 10.0.17134.0.


Solution

  • The problem is that the openFile() function does not have the proper return type to handle co_await.

    See the research and work that went into the answer I created for C++11 threads to update MFC application windows. SendMessage(), PostMessage() required? which contains a list of recommendations for various approaches to coroutines.

    This question was about using C++/WinRT with MFC but the material also applies with WinAPI.

    See as well synchronizing SDK with Windows 10 update and using WinRT with Standard C++ which contains a simple console application example using the Web Syndication async functionality to retrieve a list of URLs from an RSS feed. There are a number of links to documentation, some of which is a bit out dated now.

    Addendum: Sample Console application

    I created the following simple console application using Visual Studio 2017. I created the text file and then ran this in the debugger. I then renamed the text file and ran it again in the debugger and an exception was thrown since the file with that name no longer existed.

    See also C++/WinRT, part of Windows SDK 17134 is not compatible with Visual Studio 15.8 Preview 3 which describes a compiler option you may need to change. I did.

    // console_winrt.cpp : This file contains the 'main' function. Program execution begins and ends there.
    //
    // Requires the following changes to the project properties in the C++ compiler section.
    //   - C++ language standard must be set to C++17
    //   - Add /await to the Additional options
    
    #include "pch.h"
    
    #pragma comment(lib, "windowsapp")
    
    #include <winrt/Windows.Storage.h> 
    #include <winrt/Windows.Foundation.h>
    
    #include <iostream>
    
    winrt::Windows::Foundation::IAsyncAction  openMyFile()
    {
    
        winrt::hstring path{ L"D:\\Users\\rickc\\mytextfile.txt" };
    
        //wait for open the file 
        auto file = co_await winrt::Windows::Storage::StorageFile::GetFileFromPathAsync(path);
    
        //IStorageFile interface needed 
        auto xDate = file.DateCreated();
        std::cout << "file was found " << std::endl;
    }
    
    int main()
    {
        // initialize the WinRT apartment.
        winrt::init_apartment();
    
        auto x = openMyFile();
    
        // wait on the file access since that is all we are doing and we need to give it time.
        x.get();
        return 0;
    }
    

    I used the following properties settings.

    Properties dialog screen shot showing General Properties

    Properties dialog screen shot showing C/C++ All options