从本地C ++代码调用C ++ CX

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从本地C ++代码调用C ++ CX相关的知识,希望对你有一定的参考价值。

我需要将本机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?

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

现在我遇到错误:HRESULT_FROM_WIN32(ERROR_NOT_FOUND) : Element not found.,与本机方法相同。

也许是我的应用程序未与Win Store应用程序关联。但是我创建了UWP应用程序,但没有将其与Win Store关联,并且可以正常工作。所以我真的不知道可能是什么问题。

这里是简化代码:

标题(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();
}

Main(本地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;
}
答案

如果使用的是Visual Studio,则可以为非WinRT应用程序启用C ++ CX支持。为此,请转到“属性”->“ C / C ++”,然后选择“将Windows Runtime Extensions消耗为“是(/ ZW)”。

以上是关于从本地C ++代码调用C ++ CX的主要内容,如果未能解决你的问题,请参考以下文章

Android JNI之C/C++层调用JAVA

在c/c++中调用Java方法

从 C# 调用 C/C++ 代码

Android JNI之C/C++层调用JAVA

使用参数从 Python 调用 C/C++ 代码

从本机 c 代码 (JNI) 为 Java 中的回调函数传递多个参数