简体   繁体   English

为什么WP8.1运行时组件在对boost :: filesystem :: file_size()的调用上引发C ++异常?

[英]Why does WP8.1 runtime component throw C++ exception on call to boost::filesystem::file_size()?

Windows Phone 8.x developers porting C++ with Boost code to WP8.x are aware that several Boost binary libraries contain banned Win32 calls. Windows Phone 8.x开发人员将带有Boost代码的C ++移植到WP8.x,他们意识到几个Boost二进制库包含禁止的Win32调用。 Thus, these Boost libraries need to be ported to WP8.x. 因此,这些Boost库需要移植到WP8.x。

Steven Gates, a Microsoft engineer, ported several Boost libraries (ie, system, chrono, date_time, smart_ptr, signals2, and thread) and wrote an excellent blog describing how he did it. 微软工程师史蒂芬·盖茨(Steven Gates)移植了多个Boost库(例如,系统,计时码表,date_time,smart_ptr,signals2和线程),并撰写了出色的博客,描述了他的工作方式。

One critical Boost library he did not port is filesystem. 他没有移植的一个关键的Boost库是文件系统。 Although I am new to WinRT and runtime components, I want to attempt to port this library to Windows Phone 8.1 (WP8.1 has less banned functionality than WP8.0, and does not require RPAL ["restricted platform allow list"] for many functions). 尽管我不是WinRT和运行时组件的新手,但我想尝试将此库移植到Windows Phone 8.1(WP8.1的禁止功能比WP8.0少,并且不需要RPAL [“受限平台允许列表”]职能)。

I began by commenting out all filesystem source code that does not compile under Windows Phone 8.1, reaching a state where I could build the filesystem library for WP8.1 ARM using the following Boost b2 command: 首先,我注释掉了在Windows Phone 8.1下无法编译的所有文件系统源代码,达到了可以使用以下Boost b2命令为WP8.1 ARM构建文件系统库的状态:

b2 toolset=msvc-12.0 windows-api=phone link=static architecture=arm filesystem

My overall plan is to implement the commented-out functions one at a time, testing the ported code through a minimal WP 8.1 app. 我的总体计划是一次实现注释掉的功能,并通过最小的WP 8.1应用程序测试移植的代码。

My next step was to write a minimal Windows Phone 8.1 app together with a Windows Phone Runtime Component 8.1 project, both bundled in a single solution (the runtime component will interface with the Boost library). 我的下一步是编写一个最小的Windows Phone 8.1应用程序以及Windows Phone运行时组件8.1项目,这两个项目都捆绑在一个解决方案中(运行时组件将与Boost库连接)。 To get them working I: 为了让他们工作,我:

  • added the runtime component as a reference to the main app project 添加了运行时组件作为对主应用程序项目的引用
  • linked the Boost filesystem static library to the runtime component 将Boost文件系统静态库链接到运行时组件
  • added an API function within the runtime component called GetFileSize() that the app can invoke. 在运行时组件中添加了一个名为GetFileSize()的API函数,应用可以调用该函数。 The purpose is to exercise the boost::filesystem::file_size() function within the ported Boost library. 目的是在移植的Boost库中执行boost :: filesystem :: file_size()函数。
  • linked code to a UI button that, when pressed, calls into the runtime component to invoke the GetFileSize() function 将代码链接到UI按钮,该按钮在按下时会调用运行时组件以调用GetFileSize()函数

The problem I have is that the call to boost::filesystem::file_size() throws an exception, and it is not obvious what the problem is. 我遇到的问题是,对boost :: filesystem :: file_size()的调用引发了异常,问题不明显。

Here is the relevant code I've written. 这是我编写的相关代码。

namespace MinimalWindowsRuntimeApp
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            this.NavigationCacheMode = NavigationCacheMode.Required;
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }

        private void GetFileSize_Click(object sender, RoutedEventArgs e)
        {
            String filepath = "\\Phone\\Pictures\\Camera Roll\\WP_20140106_001.jpg";
            var newObject = new WindowsRuntimeComponent1.Class1();
            newObject.GetFileSize(filepath);
        }
    }
}

When I press the dedicated button on the Windows Phone screen it invokes the GetFileSize_Click() function. 当我按下Windows Phone屏幕上的专用按钮时,它将调用GetFileSize_Click()函数。 This code creates an instance of the WindowsRuntimeComponent1.Class1() activatable class and calls its GetFileSize () function: 这段代码创建WindowsRuntimeComponent1.Class1()可激活类的实例,并调用其GetFileSize()函数:

// Class1.cpp
#include "pch.h"
#include "Class1.h"
#include "boost/filesystem.hpp"

using namespace WindowsRuntimeComponent1;
using namespace Platform;

Class1::Class1()
{
}

int64 Class1::GetFileSize(Platform::String ^filepath)
{
    boost::filesystem::path p (filepath->Data ());
    __int64 filesize = (__int64) boost::filesystem::file_size (p);

    return filesize;
}

The intention is for the GetFileSize() function in the runtime component to instantiate a boost::filesystem::path object (which takes a wide-char string of the path) and invoke the boost::filesystem::file_size() function. 目的是让运行时组件中的GetFileSize()函数实例化boost :: filesystem :: path对象(采用路径的宽字符字符串)并调用boost :: filesystem :: file_size()函数。

The problem is that the call to file_size() throws an exception, as shown in the output window: 问题在于,对file_size()的调用会引发异常,如输出窗口所示:

First-chance exception at 0x774E59A3 in MinimalWindowsRuntimeApp.exe: Microsoft C++ exception: boost::filesystem::filesystem_error at memory location 0x0315E498.

Tracing into Boost with the native debugger shows the code in Boost's operations.cpp that fails: 使用本机调试器跟踪Boost会显示Boost的operations.cpp中的代码失败:

  BOOST_FILESYSTEM_DECL
  boost::uintmax_t file_size(const path& p, error_code* ec)
  {
    . . .
#   else  // Windows

    // assume uintmax_t is 64-bits on all Windows compilers

    WIN32_FILE_ATTRIBUTE_DATA fad;

    if (error(::GetFileAttributesExW(p.c_str(), ::GetFileExInfoStandard, &fad)== 0,
        p, ec, "boost::filesystem::file_size"))
        return static_cast<boost::uintmax_t>(-1);
    . . .    
#   endif
  }

The failure occurs while calling the Win32 API GetFileAttributesExW() function. 调用Win32 API GetFileAttributesExW()函数时会发生故障。 At the point of invocation, p.c_str() equals the expected "\\Phone\\Pictures\\Camera Roll\\WP_20140106_001.jpg". 在调用时,p.c_str()等于预期的“ \\ Phone \\ Pictures \\ Camera Roll \\ WP_20140106_001.jpg”。 The function, which is supported for Windows Phone 8.1 , fails and returns 0, which causes Boost's error() function to throw an exception. Windows Phone 8.1支持的该函数失败并返回0,这将导致Boost的error()函数引发异常。

My two questions are: 我的两个问题是:

  1. Why is the Win32 API GetFileAttributesExW function failing? 为什么Win32 API GetFileAttributesExW函数失败?
  2. Is the Windows Phone file path I pass to GetFileSize (ie, "\\Phone\\Pictures\\Camera Roll\\WP_20140106_001.jpg") the valid way to specify a file on the Windows Phone? 我传递给GetFileSize的Windows Phone文件路径(即“ \\ Phone \\ Pictures \\ Camera Roll \\ WP_20140106_001.jpg”)是否是在Windows Phone上指定文件的有效方法?

Many thanks in advance for any help you can give. 在此先感谢您提供的任何帮助。

You need to include the drive letter ("C:\\\\path\\\\to\\\\file") when creating paths on Windows. 在Windows上创建路径时,需要包括驱动器号(“ C:\\\\ path \\\\ to \\\\ file”)。 Note that in a real Windows Phone app you should never hard-code the path because the user can move stuff to the SD card. 请注意,在真实的Windows Phone应用中,永远不要对路径进行硬编码,因为用户可以将内容移动到SD卡中。 You should also never store the absolute path to a file for the same reason. 出于同样的原因,您也不应存储文件的绝对路径。 It's OK for your test though. 不过您的测试还可以。

Also, you're trying to read from the Camera Roll, which you can't do directly (you can only read protected files like that through WinRT APIs). 另外,您正在尝试从相机胶卷中读取内容,而无法直接读取(您只能通过WinRT API读取受保护的文件)。 But here is a sample showing it working (replace App::App from a new, blank C++ Windows Phone project): 但是,这里有一个示例显示它正常工作(从新的空白C ++ Windows Phone项目中替换App :: App):

App::App()
{
  InitializeComponent();
  Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending);

  auto path = std::wstring(Windows::ApplicationModel::Package::Current->InstalledLocation->Path->Data()) + L"\\Assets\\SplashScreen.scale-240.png";
  std::wstringstream ss;
  ss << L"Path is " << path << std::endl;
  WIN32_FILE_ATTRIBUTE_DATA data{};
  if (GetFileAttributesExW(path.c_str(), GET_FILEEX_INFO_LEVELS::GetFileExInfoStandard, &data))
  {
    ss << L"Size is " << (((LONG)data.nFileSizeHigh << sizeof(DWORD)) + (LONG)data.nFileSizeLow) << std::endl;
  }
  else
  {
    ss << L"Can't get size info: " << GetLastError() << std::endl;
  }
  OutputDebugString(ss.str().c_str());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 属于Boost Filesystem的file_size()的C ++错误 - C++ Error for file_size() which belongs to Boost Filesystem 使用带有空格的路径时出现boost :: filesystem :: file_size错误 - boost::filesystem::file_size error when using a path with whitespace 为什么目录上的 std::filesystem::file_size 留给实现? - Why is std::filesystem::file_size on directories left to the implementaiton? 如何从[C#WP8.1 WRT / SL]项目中调用[非托管C ++ DLL函数] - How to Call [Unmanaged C++ DLL func] from [C# WP8.1 WRT/SL] project 为什么 std::filesystem::file_size(file) 与实际文件大小不同? - Why std::filesystem::file_size(file) is differnt with real file-size? std::filesystem:file_size 给我一个不连贯的值 - std::filesystem:file_size send me an incoherent value 使用C ++ Baclground-Task将解决方案部署到物理WP8.1设备 - Deploying Solution with C++ Baclground-Task to physical WP8.1 Device WP8.1认证-6.5.1-使用XAML / C ++的初始启动功能 - WP8.1 Certification - 6.5.1 - Initial launch functionality using XAML/C++ boost :: filesystem :: path(std :: wstring)抛出异常 - boost::filesystem::path(std::wstring) throw exception 使用boost :: filesystem :: path作为参数的C ++构造函数调用-没有任何反应 - C++ constructor call with boost::filesystem::path as argument - nothing happening
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM