简体   繁体   English

我可以使用 C++/WinRT 编写一个 DLL 以供 Windows 桌面应用程序(不是 UWP)或作为 Unity 插件使用吗?

[英]Can I write a DLL with C++/WinRT to be consumed by a windows desktop app(not UWP) or as a Unity plugin?

I've experimented writing a simple DLL with C++/WinRT.我已经尝试用 C++/WinRT 编写一个简单的 DLL。 It can be imported and run without any problems by a Windows desktop app (I've tried writing two desktop apps, one in C# and another in C++/WinRT.)它可以通过 Windows 桌面应用程序毫无问题地导入和运行(我尝试编写两个桌面应用程序,一个使用 C#,另一个使用 C++/WinRT。)

When I import it as a plugin for Unity, it runs fine, but causes Unity to freeze on exit.当我将它作为 Unity 的插件导入时,它运行良好,但会导致 Unity 在退出时冻结。 I've then narrowed it down to some possible threading issue.然后我将其缩小到一些可能的线程问题。 Specifically, if the plugin calls back Unity on a thread the plugin spawns, the call goes through, and the code runs fine, but when I try to exit Unity editor, it freezes.具体来说,如果插件在插件生成的线程上回调 Unity,则调用会通过,并且代码运行良好,但是当我尝试退出 Unity 编辑器时,它会冻结。

Here's a short sample code for the DLL.这是 DLL 的简短示例代码。 #include "stdafx.h" #include “stdafx.h”

#include <winrt\base.h>

extern "C"
{
    typedef void(*testCallback)(Info info);

    __declspec(dllexport) void TryAsyncWinRT(testCallback callback);
}

using namespace winrt;
using namespace Windows::Foundation;

static testCallback handler;

IAsyncAction JustDoWork()
{
    co_await winrt::resume_background();

    int result{};

    /*
    Some calculation...
    */

    if (handler) {
        handler(result);
    }

    co_return;
}

void TryAsyncWinRT(testCallback callback)
{
    handler = callback;
    JustDoWork();
}

The compiler I used is Visual Studio 2017, with C++/WinRT extension installed.我使用的编译器是 Visual Studio 2017,安装了 C++/WinRT 扩展。 I did not change anything in the "DllMain" supplied by Visual Studio.我没有更改 Visual Studio 提供的“DllMain”中的任何内容。 I did not call "init_apartment()" in the DLL code as I suppose that's done by the host app, as each app can have only one multi-threaded apartment.我没有在 DLL 代码中调用“init_apartment()”,因为我认为这是由主机应用程序完成的,因为每个应用程序只能有一个多线程单元。

If I don't callback into Unity, there's no problem.如果我不回调到 Unity,就没有问题。 If I just use the standard library's thread utilities, Unity works fine too.如果我只使用标准库的线程实用程序,Unity 也可以正常工作。

void JustDoWork()
{
    int result{};

    /*
    Some calculation...
    */

    if (handler) {
        handler(result);
    }
}

void TryAsync(testCallback callback)
{
    handler = callback;
    std::thread(JustDoWork).detach();
}

I feel that I must be missing something, but I couldn't find any documentation on how to write a regular DLL (not a Windows Runtime Component) using C++/WinRT.我觉得我一定遗漏了一些东西,但我找不到任何关于如何使用 C++/WinRT 编写常规 DLL(不是 Windows 运行时组件)的文档。

Could any kind soul shed some light?任何善良的灵魂都可以发光吗? Thanks a lot!非常感谢!

when trying to implement BLE I stumbled across the same problem I guess.在尝试实现 BLE 时,我偶然发现了同样的问题。 Specifically my C# program crashed when I tried to call a C# callback inside of the C++ winrt dll, and often it crashed when I used C++ winrt allocated memory inside the C# program even though I tried to follow the memory allocation advices.具体来说,当我尝试在 C++ winrt dll 中调用 C# 回调时,我的 C# 程序崩溃了,而且当我在 C# 程序中使用 C++ winrt 分配的内存时,即使我尝试遵循内存分配建议,它也经常崩溃。

I ended up avoiding marshalled callbacks completely and implement the mechanisms via poll-functions.我最终完全避免了编组回调,并通过轮询函数实现了这些机制。 Also I allocated all memory needed for function calls on the C# side.我还分配了 C# 端函数调用所需的所有内存。

For me that feels like a workaround but it also feels pretty safe.对我来说,这感觉像是一种解决方法,但也感觉很安全。 You can see an example of how I converted a callback to polling here .您可以在此处查看我如何将回调转换为轮询的示例。

您必须在 exe 主线程(UI 线程)中释放 C++/WinRT DLL 的所有资源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM