Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么WP8.1运行时组件抛出C++;调用boost::filesystem::file_size()时出现异常? Windows Phone 8 .x开发人员将C++与Boost代码移植到WP8. X中,知道几个Boost二进制库包含禁用的Win32调用。因此,这些Boost库需要移植到WP8.x_C++_Windows Phone 8_Boost - Fatal编程技术网

为什么WP8.1运行时组件抛出C++;调用boost::filesystem::file_size()时出现异常? Windows Phone 8 .x开发人员将C++与Boost代码移植到WP8. X中,知道几个Boost二进制库包含禁用的Win32调用。因此,这些Boost库需要移植到WP8.x

为什么WP8.1运行时组件抛出C++;调用boost::filesystem::file_size()时出现异常? Windows Phone 8 .x开发人员将C++与Boost代码移植到WP8. X中,知道几个Boost二进制库包含禁用的Win32调用。因此,这些Boost库需要移植到WP8.x,c++,windows-phone-8,boost,C++,Windows Phone 8,Boost,微软工程师史蒂文·盖茨(Steven Gates)移植了几个Boost库(即system、chrono、date_-time、smart_-ptr、signals2和thread),并描述了他是如何实现的 他没有移植的一个关键的Boost库是文件系统。虽然我不熟悉WinRT和运行时组件,但我想尝试将此库移植到Windows Phone 8.1(WP8.1的禁用功能比WP8.0少,并且许多功能不需要RPAL[“受限平台允许列表”) 我首先注释掉所有未在Windows Phone 8.1下编译的文件

微软工程师史蒂文·盖茨(Steven Gates)移植了几个Boost库(即system、chrono、date_-time、smart_-ptr、signals2和thread),并描述了他是如何实现的

他没有移植的一个关键的Boost库是文件系统。虽然我不熟悉WinRT和运行时组件,但我想尝试将此库移植到Windows Phone 8.1(WP8.1的禁用功能比WP8.0少,并且许多功能不需要RPAL[“受限平台允许列表”)

我首先注释掉所有未在Windows Phone 8.1下编译的文件系统源代码,达到可以使用以下Boost b2命令为WP8.1 ARM构建文件系统库的状态:

b2 toolset=msvc-12.0 windows-api=phone link=static architecture=arm filesystem
我的总体计划是一次实现一个注释掉的函数,通过一个最小的wp8.1应用程序测试移植的代码

我的下一步是编写一个最小的Windows Phone 8.1应用程序和一个Windows Phone运行时组件8.1项目,两者都捆绑在一个解决方案中(运行时组件将与Boost库接口)。为了让它们工作,我:

  • 添加运行时组件作为对主应用程序项目的引用
  • 将Boost文件系统静态库链接到运行时组件
  • 在应用程序可以调用的运行时组件GetFileSize()中添加了一个API函数。其目的是在移植的boost库中执行boost::filesystem::file_size()函数
  • 链接到UI按钮的代码,按下该按钮时,将调用运行时组件以调用GetFileSize()函数
我遇到的问题是,对boost::filesystem::file_size()的调用引发了一个异常,问题是什么并不明显

以下是我编写的相关代码

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);
        }
    }
}
当我按下Windows Phone屏幕上的专用按钮时,它将调用GetFileSize_Click()函数。此代码创建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;
}
其目的是让运行时组件中的GetFileSize()函数实例化boost::filesystem::path对象(它获取路径的宽字符字符串)并调用boost::filesystem::file_size()函数

问题是调用file_size()会引发异常,如输出窗口中所示:

First-chance exception at 0x774E59A3 in MinimalWindowsRuntimeApp.exe: Microsoft C++ exception: boost::filesystem::filesystem_error at memory location 0x0315E498.
使用本机调试器跟踪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
  }
BOOST\u FILESYSTEM\u DECL
boost::uintmax\u t文件大小(常量路径和p,错误代码*ec)
{
. . .
#else//Windows
//假设所有Windows编译器上的uintmax\u t为64位
WIN32_文件_属性_数据时尚;
如果(错误(::GetFileAttributesExW(p.c_str(),::GetFileExInfo标准,&fad)==0,
p、 ec,“boost::filesystem::file_size”))
返回静态_cast(-1);
. . .    
#恩迪夫
}
调用Win32 API GetFileAttributesXw()函数时发生故障。在调用时,p.c_str()等于预期的“\Phone\Pictures\Camera Roll\WP_20140106_001.jpg”。函数失败并返回0,这会导致Boost的error()函数引发异常

我的两个问题是:

  • 为什么Win32 API GetFileAttributesExW函数失败
  • 我传递给GetFileSize的Windows Phone文件路径(即“\Phone\Pictures\Camera Roll\WP\u 20140106\u 001.jpg”)是否是在Windows Phone上指定文件的有效方法

  • 非常感谢您提供的帮助。

    在Windows上创建路径时,您需要包括驱动器号(“C:\\path\\to\\file”)。请注意,在真正的Windows Phone应用程序中,您不应该硬编码路径,因为用户可以将内容移动到SD卡。出于同样的原因,您也不应该存储文件的绝对路径。不过,你的测试没问题

    此外,您还试图从摄影机卷中读取,这是无法直接执行的(您只能通过WinRT API读取受保护的文件)。但这里有一个示例显示它正在工作(替换APP:从一个新的,空白的C++ Windows Phone项目中的应用程序):

    App::App()
    {
    初始化组件();
    Suspending+=ref新的SuspendingEventHandler(this,&App::OnSuspending);
    自动路径=std::wstring(Windows::ApplicationModel::Package::Current->InstalledLocation->path->Data())+L“\\Assets\\SplashScreen.scale-240.png”;
    std::wstringstream ss;
    
    ss我不认为在访问Windows Phone设备上的文件时会使用驱动器号(例如“C:”),而不是访问Windows桌面上的文件。我绝对同意从不硬编码路径,但正如你所说,我正在尝试启动并运行一个“快速且肮脏”的测试应用程序。因此,如果我的手机名为“Windows Phone Nokia Lumia 520 XXX”(如关于页面所示),我有一个文件位于[主页]\Phone\pictures\screenshots\foobar.jpg中,访问该文件的确切硬编码路径字符串是什么?它以“C:”开头(如果您在内部设备上,Windows Phone是Windows:-)另一个问题是,您试图获取一个您无法直接访问的文件(相机卷)-像这样受保护的位置只能通过代理WinRT API访问。我用代码片段更新了原始答案。伟人所见略同:-)昨天我在WinRT中面对代理访问的愉快世界。我读了一篇有趣的MSDN博客()你和它似乎都表明存在无法转换为路径的WinRT存储库。我想知道我是否应该修改Boost代码以使用WinRT访问函数而不是传统的路径API。给你一分钱…:-)嗯,我认识这个名称。你是P吗
    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());
    }