unity3d - 带有 native 库的 HoloLens 回调

标签 unity3d uwp callback hololens

我的 目标调用方法 ,在 中实现团结 代码,来自 我的 UWP DLL . (所以我可以在我的 HoloLens 项目中使用它们)

我尝试了一个更大的项目,但失败了。因此我写了一个简单的例子,以便更容易发现错误并排除其他影响。
但是,我仍然遇到同样的错误。

我的工作环境:

  • 操作系统为 Windows 10 的 64 位计算机
  • 微软 Visual Studio 社区
    2015 版本 14.0.25431.01 更新 3
  • HoloLens 模拟器 10.0.14393.0
  • Unity 5.5.0f3 个人版(64 位)

  • 创建 UWP DLL:

    为了解决这个问题,我在 Visual Studio 2015 中创建了一个 C++ DLL(Windows 通用),如下所示:

    新建项目 > Visual C++ > Windows > 通用 > DLL(通用 Windows)

    项目自动生成后,我添加了我的代码。
    所以代码看起来像这样:

    native 库代码:
    SimpleProjectDLL.cpp:
    
    #include "pch.h"
    #define DLL_EXPORT __declspec(dllexport)
    
    typedef void(*CB_V)();
    typedef void(*CB_V_VI)(const char * a, int b);
    
    CB_V_VI cb_native_log;
    CB_V cb_call;
    
    void log()
    {
        // this method makes problems !
        cb_native_log("Call for callback", 1);
    }
    
    extern "C" {
        DLL_EXPORT void initInterfaceCallbacks(
            CB_V_VI native_log,
            CB_V call
        ) {
            cb_native_log = native_log;
            cb_call = call;
        }
    
        DLL_EXPORT void callSmth() 
        {
            cb_call();
        }
    
        DLL_EXPORT int getSomeInt()
        {
            return 42;
        }
    
        DLL_EXPORT void initCallback() 
        {
            log();
        }
    }
    

    SimpleProjectDLL.h 正在准备代表:
    SimpleProjectDLL.h:
    
    #pragma once
    #include <cstdint>
    #define DLL_EXPORT __declspec(dllexport)
    
    extern "C" 
    {
        typedef void(*CB_V)();
        typedef void(*CB_V_VI)(const char * a, int b);
    }
    

    我没有对自动生成的文件 dllmain.cpp、pch.cpp、pch.h 或 targetver.h 进行任何更改。

    最后,我为“发布”模式和体系结构“x86”构建项目以生成 DLL 文件。
    DLL 文件的位置现在是:项目根文件夹/发布/SimpleProject/SimpleProjectDLL.dll .

    ----------

    下一步我创建了一个 新的 Unity 项目 添加了 HoloLens-Toolkit 并确保新项目在模拟器上运行良好。

    Unity 项目代码:

    之后我添加了 SimpleProjectDLL.dll 在 Asset-Folder 中并实现了以下代码:

    首先,我们需要创建代表之间的连接。
    Cpp.cs 为代表们做准备:
    Cpp.cs
    
    using UnityEngine;
    using System;
    using System.Runtime.InteropServices;
    
    namespace Cpp
    {
        delegate void DelegateV();
        delegate void DelegateVVi(IntPtr a, int b);
    }
    

    SimpleInterfaceCpp.cs 初始化连接:
    SimpleInterfaceCpp.cs
    
    using Cpp;
    using System.Runtime.InteropServices;
    using UnityEngine;
    
    public static class SimpleInterfaceCpp
    {
        public static void Init()
        {
             initInterfaceCallbacks(
                SimpleInterface.NativeLog,
                SimpleInterface.Call
            );
        }
    
        [DllImport(SimpleInterface.DLL)]
        private static extern void initInterfaceCallbacks(
            DelegateVVi native_log,
            DelegateV call
        );
    }
    

    主要的:
    MainController.cs
    
    using UnityEngine;
    using System.Collections;
    using System.Runtime.InteropServices;
    
    public class MainController : MonoBehaviour 
    {
        void Start ()
        {
            SimpleInterfaceCpp.Init();
            SimpleInterface.TestCalls();
        }
    }
    

    SimpleInterface.cs 正在调用方法:
    SimpleInterface.cs
    
    using System;
    using UnityEngine;
    using System.Runtime.InteropServices;
    using AOT;
    using IntPtr = System.IntPtr;
    using Cpp;
    
    using StringReturn = System.IntPtr;
    
    public class SimpleInterface
    {
        public const string DLL = "SimpleProjectDLL";
    
        public static void TestCalls()
        {
            // This works fine
            int number = getSomeInt();
            Debug.Log("getSomeInt: " + number);
    
            // This also works fine and outputs "--- A callback ---"
            callSmth();
    
            // This call gives the output "call_log: native log" but crashes afterwards !
            initCallback();
    
        }
    
        [MonoPInvokeCallback(typeof(DelegateVVi))]
        public static void NativeLog(IntPtr logMessage,
             int logLevel)
        {
            string result = StringFromCReturn(logMessage);
            UnityEngine.Debug.Log(result); // outputs "call_log: native log"
        }
    
        [MonoPInvokeCallback(typeof(DelegateV))]
        public static void Call()
        {
            UnityEngine.Debug.Log("--- A callback---");
        }
    
        [DllImport(DLL)]
        private static extern void initCallback();
        [DllImport(DLL)]
        private static extern void callSmth();
        [DllImport(DLL)]
        private static extern int getSomeInt();
    
        public static string StringFromCReturn(StringReturn someReturnVal)
        {
            return Marshal.PtrToStringAnsi(someReturnVal);
        }
    }
    

    现在,如果我创建一个 SLN,在 Visual Studio 中打开项目并使用“HoloLens Emulator”启动它,我会得到以下输出:
    getSomeInt: 42
    
    (Filename: C:/buildslave/unity/build/artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51)
    
    
    --- A callback---
    
    (Filename: C:/buildslave/unity/build/artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51)
    
    
    call_log: native log
    
    (Filename: C:/buildslave/unity/build/artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51)
    
    
    The program '[1932] SimpleProject.exe' has exited with code -1073740791 (0xc0000409).
    

    之后,应用程序就关闭了。

    所以我的问题 是,有谁知道问题可能是什么?

    这是在 HoloLens 项目中使用回调的正确方法吗?

    或者有人知道如何找到代码“-1073740791 (0xc0000409)”的错误描述吗?

    附加信息:
    我也在一个真正的 HoloLens 设备上尝试过,同样的问题,所以问题不在于模拟器。

    最佳答案

    错误是 STATUS_STACK_BUFFER_OVERRUN。该调用破坏了调用堆栈。

    在 SimpleProjectDLL.cpp 和 SimpleProjectDLL.h 中有不同的回调声明。 cpp文件使用“CPP”调用 session ,header使用“C”调用 session 。

    您应该通过删除来更改 SimpleProjectDLL.cpp

    typedef void(*CB_V)();
    typedef void(*CB_V_VI)(const char * a, int b);
    

    并添加
    #include "SimpleProjectDLL.h"
    

    关于unity3d - 带有 native 库的 HoloLens 回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41853963/

    相关文章:

    c# - 圆上的随机点

    c# - Unity找不到其他GameObject的脚本

    unity3d - Unity 项目是否有标准/推荐的目录结构?

    c# - 制作时钟 UWP (C#)

    javascript - 循环函数(Javascript 回调帮助)

    c# - 隐藏继承成员警告

    c# - x :Bind works but Binding doesn't (opposite to most Q&A found)

    dependency-properties - 是否可以使用已编译的绑定(bind) (x :Bind) with Relative Source, Templated Parent

    c++ - 指向具有不同参数的成员函数的指针的容器

    Javascript 通过本地引用传递回调