0

该场景是新的,我相信它可能是 cpp-winrt 模块或 vc 编译器中的错误。

问题
1. 使用通用 windows 的 cpp-winrt 模板创建一个“windows 运行时组件”。
2. 记下 idl 文件中定义的命名空间名称。默认情况下,idl 文件被命名为 class.idl。
3. 使用类向导将“新标准 cpp 类”添加到项目中。
4. 将新类放在 idl 文件中定义的相同命名空间名称下。
5. 构建项目。
一个。构建应该成功。
6.在运行时实现类中使用标准的cpp类。
7. 现在再次尝试构建项目。
一个。这次构建将失败。

原因
1. cppwinrt.exe 从 idl 文件生成源文件。
2.运行时实现类命名空间以“winrt”为前缀。
3.标准的cpp类不以命名空间“winrt”为前缀。
4. vc 编译器期望标准 cpp 类命名空间从“winrt”开始
5.否则即使您尝试使用完全限定的命名空间名称,名称解析也会失败。

示例运行时 idl 文件


namespace NMLevel1.NMLevel2
{
    [default_interface]
    runtimeclass Class
    {
        Class();
        void RuntimeMethod1();
        Int32 RuntimeMethod2(Int32 arg1);
        String RuntimeMethod3(String arg1);
        Int32 MyProperty;
    }
}

示例标准 cpp 文件

#pragma once
#include <string>
using namespace std;

namespace NMLevel1::NMLevel2
{
    class StdCPPClass
    {
    public:
        StdCPPClass();
        virtual ~StdCPPClass();

        void method1();
        int method2(int arg1);
        wstring method3(wstring arg1);
    };
}

示例运行时类实现

#include "pch.h"
#include "Class.h"
#include "NMLevel1.NMLevel2.Class.g.cpp"
#include "StdCPPClass.h"

using namespace winrt;
using namespace Windows::Foundation;

namespace winrt::NMLevel1::NMLevel2::implementation
{
    void Class::RuntimeMethod1()
    {
        NMLevel1::NMLevel2::StdCPPClass stdcls;

        Uri uri(L"http://aka.ms/cppwinrt");
        //printf("Hello, %ls!\n", uri.AbsoluteUri().c_str());
        printf("RuntimeMethod1(): Hello, %ls!\n", stdcls.method3(uri.AbsoluteUri().c_str()).c_str());
    }
}

NMLevel1::NMLevel2::StdCPPClass stdcls; 不允许在命名空间前加上 winrt 前缀。

这是无法克服的错误还是设计限制?或如何在 idl 和 cpp 文件中使用相同的命名空间“NMLevel1::NMLevel2”?

4

1 回答 1

1

C++ 中的名称查找相当复杂,尤其是当命名空间基本上通过using声明合并时。为了帮助编译器识别您想要的名称,您必须明确并使用完全限定名称(与示例中的限定名称相反)。

你必须改变

void Class::RuntimeMethod1()
{
    NMLevel1::NMLevel2::StdCPPClass stdcls;
    // ...
}

void Class::RuntimeMethod1()
{
    ::NMLevel1::NMLevel2::StdCPPClass stdcls;
    // ...
}

请注意领先的::范围解析,它将查找限制在全局范围(或​​通过声明引入全局​​命名空间的命名空间using)。您可以在此处找到更多信息:合格名称查找

于 2019-11-02T08:36:51.620 回答