user3743210
user3743210

Reputation: 211

How to call StorageFile.OpenReadAsync in C++/winrt?

In my continuing efforts to load a collection of .svg files in C++/winrt I'm encountering a mysterious link error. I'd like to try using CanvasSvgDocument.ReadAsync(resourceCreator, filestream). To get there it is first necessary to get the stream from the StorageFile, and this would appear to be the way to do it (nextFile, a StorageFile, is already loaded in this example). This is of course within a method defined as an IAsyncAction. I'll list the #includes and namespaces from the top of the file.

#include "winrt/Windows.ApplicationModel.h"
#include "winrt/Windows.Storage.h"
#include "winrt/Windows.Storage.Streams.h"
#include "winrt/Windows.Foundation.Collections.h"
#include "winrt/Windows.Storage.Search.h"
#include "winrt/Windows.UI.Core.h"
#include "winrt/Windows.UI.Xaml.Media.h"
#include "pch.h"

using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::Storage;
using namespace Windows::Storage::Provider;
using namespace Windows::Storage::Search;
using namespace Windows::Storage::Streams;

Here is the problematic call:

IRandomAccessStreamWithContentType fileStream = co_await nextFile.OpenReadAsync();

That produces a link error that I'll put in below. It doesn't matter whether or not I try the fully qualified name of the fileStream result:

winrt::Windows::Storage::Streams::IRandomAccessStreamWithContentType fileStream = co_await nextFile.OpenReadAsync();

either way I get this link error:

Error LNK2019 unresolved external symbol "public: struct winrt::Windows::Foundation::IAsyncOperation __thiscall winrt::impl::consume_Windows_Storage_Streams_IRandomAccessStreamReference::OpenReadAsync(void)const " (?OpenReadAsync@?$consume_Windows_Storage_Streams_IRandomAccessStreamReference@UIStorageFile@Storage@Windows@winrt@@@impl@winrt@@QBE?AU?$IAsyncOperation@UIRandomAccessStreamWithContentType@Streams@Storage@Windows@winrt@@@Foundation@Windows@3@XZ) referenced in function "public: struct winrt::Windows::Foundation::IAsyncAction __thiscall AppEngine::ResourceManager::LoadSvgResources$_ResumeCoro$2(struct winrt::Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl)" (?LoadSvgResources$_ResumeCoro$2@ResourceManager@AppEngine@@QAE?AUIAsyncAction@Foundation@Windows@winrt@@UCanvasControl@Xaml@UI@Canvas@Graphics@Microsoft@6@@Z)

I've also tried using auto as the result type, no luck. What is the right way to obtain a stream using OpenReadAsync() in C++/winrt?

Upvotes: 0

Views: 746

Answers (1)

IInspectable
IInspectable

Reputation: 51345

You are apparently compiling with precompiled headers enabled (hinted to by the #include "pch.h" directive). When doing so, the header used to generate the precompiled header must be included on the first non-empty, non-comment line in the compilation unit consuming it.

The /Yu (Use Precompiled Header File) documentation has the relevant information:

The compiler treats all code occurring before the .h file as precompiled. It skips to just beyond the #include directive associated with the .h file, uses the code contained in the .pch file, and then compiles all code after filename.

In other words, all your includes preceding the #include "pch.h" directive are ignored. Since C++/WinRT is a header-only library, this will eventually result in linker errors.

To fix the issue

  • Move the #include "pch.h" directive to the very top of the file, or
  • Replace the #include directive with the /FI (Name Forced Include File) compiler option on the relevant compilation units, or
  • Disable use of precompiled headers.

Upvotes: 4

Related Questions