Мне нужно открыть файл, который хранится в пакете моего приложения, используя _wfopen_s
функция, но она возвращает FILE
объект с NULL _ptr
, Это происходит так:
var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync("test\\test.ext");
var nativeWorker = new NativeWorker(file.Path);
<...>
auto err = _wfopen_s(&this->_myFile, fileName->Data(), L"rb");
err
возвращается 0, но отладчик показывает, что где-то произошла ошибка в msvcr110d.dll, и все поля this->_myFile
NULL, кроме _flag
что равно 1 и _file
это равно 3.
Чтобы выяснить, является ли это проблемой с самим файлом, я написал фрагмент, подобный показанному здесь: Как предотвратить потерю сохраненных данных при обновлении приложения на WP8 с помощью cpp. Это выглядит так:
FILE *tmp;
auto tmpPath = Windows::Storage::ApplicationData::Current->LocalFolder->Path + "\\tmp.txt";
auto tmpErr = _wfopen_s(&tmp, tmpPath->Data(), L"w");
Результат почти такой же, за исключением того, что _flag
собственностью tmp
теперь равно 2.
Я создаю стандартное приложение XAML, и это делается внутри компонента времени выполнения Windows Phone. Но я уверен, что это не так, потому что я создал собственное 3D-приложение, и там происходит то же самое. Это даже происходит в компоненте среды выполнения Магазина Windows, на который ссылается проект модульных тестов.
Я не могу отказаться от использования FILE
struct, потому что она запрашивается сторонней DLL, которую я использую. Может быть, есть разрешение, которое я пропустил, или, может быть, есть способ конвертировать WinRT IRandomAccessStream
в FILE
так что я мог бы просто использовать StorageFile
API? Последнее сделало бы мою жизнь намного проще 🙂
Это ожидаемое поведение семейства функций fopen. FILE*
возвращается не ноль; _ptr
член указан FILE
может быть нулевым
_ptr
member указывает на позицию в буфере потока, в которой будет происходить следующее чтение или запись. Буфер инициализируется лениво, поэтому, поскольку вы еще не сделали никаких операций ввода-вывода, для потока не было создано ни одного буфера. Таким образом _ptr
является нулевым (и _base
является нулевым и _cnt
это ноль).
Ваш звонок в _wfopen_s
добивается успеха. Если это не удалось, то FILE*
сам по себе будет нулевым, а возвращенный код состояния будет отличным от нуля.
Есть ли способ конвертировать WinRT
IRandomAccessStream
вFILE
?
Нет.
Ну, проблема была в отсутствии опыта 🙂 Похоже, что сторонняя DLL, которую я скомпилировал, использует среду выполнения C ++, отличную от компонента среды выполнения Windows, поэтому проблема заключается в несовместимости указателя FILE *. Решение состоит в том, чтобы либо не передавать указатель FILE * на эту DLL из компонента WinRT (и использовать другие функции), либо пытаться создавать компоненты DLL и WinRT с использованием одной и той же среды выполнения (хотя я не уверен, что это возможно, поскольку кажется, что Windows Компоненты времени выполнения используют специальную среду выполнения приложения.