[英]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: 为了让他们工作,我:
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: 我的两个问题是:
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.