【发布时间】: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 类的公共接口的一部分。
我有两个问题:
- 如何在 C++CX 类中使用本机指针?
- 我可以使用其他方法从本机 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;
}
【问题讨论】:
-
我知道这一点,但我在native code 中很难做到这一点,所以我正在尝试不同的方法。
-
C++/WinRT 是本机标准 C++ 代码。没有编译器生成的代码,就像 C++/CX 一样。
-
请注意,如果您想将内容排除在 WinRT 界面之外,您可以使用
internal而不是private/friendhack。也就是说,哪一行给了你错误?你的主要应用是什么类型的项目?它是 UWP 应用还是控制台 EXE(在这种情况下,它是否包装在 AppX 中并正确安装)? -
您是否创建并安装了 AppX 包?如果你想使用推送通知,你不能只运行 EXE。
标签: c++ windows-runtime c++-cx