【问题标题】:Call C++CX from native C++ code从本机 C++ 代码调用 C++CX
【发布时间】:2019-10-25 14:05:43
【问题描述】:

我需要将原生 C++ 代码与 C++CX 代码结合起来。 我们的产品主要是原生 C++,我需要访问 win10 功能(PushNotifications)。但此功能是用 WinRT 编写的,因此可以从 C++CX、C#... 访问,但不能直接从 C++ 访问。

是的,我知道现在您会告诉我这是可能的,因为 C++CX 最终被编译为本机代码。在这种情况下,请查看我之前的帖子。CreatePushNotificationChannelForApplicationAsync in native C++

所以我正在寻找其他选择。我想创建 C++CX DLL,然后将其加载到 C++ 本机应用程序中。但我也失败了,因为我无法在 C++CX 类中使用本机回调。我需要注册回调或接口,当通知到来时将触发。但是我注册不了。因为本机指针不能成为 C++CX 类的公共接口的一部分。

我有两个问题:

  1. 如何在 C++CX 类中使用本机指针?
  2. 我可以使用其他方法从本机 C++ 访问此 WinRT COM 吗?

更新: 我发现了如何修复编译器错误,但它仍然无法正常工作。 将使用本机指针的成员函数声明为私有,然后声明可以访问该私有成员的 friend 函数。

现在我收到错误:HRESULT_FROM_WIN32(ERROR_NOT_FOUND) : Element not found.,这与我的本地方法相同。

也许问题是我的应用程序没有与 win 商店应用程序关联。但是我创建了 UWP 应用程序,我没有将它与 win 商店相关联并且它可以工作。所以我真的不知道可能是什么问题。

这里是简化的代码:

header(DLL接口声明)

#pragma once
#include <string>

class IEventHandler
{
public:
    virtual void UriRefreshAsync(std::wstring&& uri) = 0;
    virtual void OnNotify(std::wstring&& content) = 0;
};

extern "C" 
{
    __declspec(dllexport) void RegisterEventHandler(IEventHandler* handler);
}

定义(用/ZW编译的DLL定义)

#include <windows.h>
#include <collection.h>
#include <ppltasks.h>
#include <wrl.h>
#include <wrl/wrappers/corewrappers.h>
#include "wns.h"

using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::Networking::PushNotifications;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace concurrency;

namespace WnsPushAPI
{
public ref class WnsWrapper sealed
{
public:
    WnsWrapper() : winRT(RO_INIT_MULTITHREADED) {};

    static WnsWrapper^ Instance() { return singleton ? singleton : singleton = ref new WnsWrapper(); }

    void ObtainUri()
    {
        IAsyncOperation<PushNotificationChannel^>^ channelOperation = PushNotificationChannelManager::CreatePushNotificationChannelForApplicationAsync();
        auto channelTask = create_task(channelOperation);
        channelTask.then([this](PushNotificationChannel^ channel) {
            eventHandler->UriRefreshAsync(std::wstring(channel->Uri->Data()));
            channel->PushNotificationReceived += ref new TypedEventHandler<PushNotificationChannel^, PushNotificationReceivedEventArgs^>(this, &WnsWrapper::OnNotify);
        }, task_continuation_context::use_current());
    }

    void OnNotify(PushNotificationChannel^ sender, PushNotificationReceivedEventArgs^ e)
    {
        if ( e->NotificationType == PushNotificationType::Raw )
        {
            eventHandler->OnNotify(std::wstring(e->RawNotification->Content->Data()));
        }
        e->Cancel = true;
    };
private:

    void RegisterEventHandler(IEventHandler* handler) { eventHandler = handler; };

    friend void ::RegisterEventHandler(IEventHandler* handler);

    RoInitializeWrapper winRT;
    IEventHandler* eventHandler = nullptr;
    std::wstring uri;
    static WnsWrapper^ singleton;
};

WnsWrapper^ WnsWrapper::singleton = nullptr;
}

void RegisterEventHandler(IEventHandler* handler)
{
    WnsPushAPI::WnsWrapper::Instance()->RegisterEventHandler(handler);
}

void GetUriAsync()
{
    WnsPushAPI::WnsWrapper::Instance()->ObtainUri();
}

主要(原生 C++ 应用程序)

#include "../wns/wns.h"
#include <windows.h>
#include <iostream>
using namespace std;

class Events : public IEventHandler
{
public:
    virtual void UriRefreshAsync(std::wstring&& uri) 
    {
        wcout << uri << endl;
    };

    virtual void OnNotify(std::wstring&& content) { /*trigger notify*/ };
};

int main(char* argv[], int argc)
{
    Events events;
    RegisterEventHandler(&events);
    GetUriAsync();

    Sleep(100*1000);
    return 0;
}

【问题讨论】:

  • C++/CX 只是一种语言扩展,可以更轻松地访问 WinRT 类型。它们仍然是 COM 对象,并且可以像任何其他 COM 对象一样从本机 C++ 访问。您可以使用WRL 来简化此操作,或者使用C++/WinRT(Windows 运行时的标准 C++ 语言投影,目前仅作为预览版提供)。
  • 我知道这一点,但我在native code 中很难做到这一点,所以我正在尝试不同的方法。
  • C++/WinRT 本机标准 C++ 代码。没有编译器生成的代码,就像 C++/CX 一样。
  • 请注意,如果您想将内容排除在 WinRT 界面之外,您可以使用 internal 而不是 private / friend hack。也就是说,哪一行给了你错误?你的主要应用是什么类型的项目?它是 UWP 应用还是控制台 EXE(在这种情况下,它是否包装在 AppX 中并正确安装)?
  • 您是否创建并安装了 AppX 包?如果你想使用推送通知,你不能只运行 EXE。

标签: c++ windows-runtime c++-cx


【解决方案1】:

如果您使用的是 Visual Studio,则可以为非 WinRT 应用程序启用 C++ CX 支持。为此,请转到属性->C/C++ 并选择使用 Windows 运行时扩展为是 (/ZW)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-21
    • 1970-01-01
    相关资源
    最近更新 更多