提问人:alexfeh 提问时间:1/25/2017 最后编辑:JoshDMalexfeh 更新时间:8/23/2019 访问量:675
使用本机库的 HoloLens 回调
HoloLens Callbacks with Native Library
问:
我的目标是从我的 UWP DLL 调用在 Unity 代码中实现的方法。(因此我可以在我的 HoloLens 项目中使用它们)
我尝试过一个更大的项目,但失败了。因此,我写了一个简单的例子,以便更容易找到错误并排除其他影响。 但是,我仍然收到同样的错误。
我的工作环境:
- 操作系统为 Windows 10 的 64 位计算机
- Micsrosoft Visual Studio 社区 2015年版本14.0.25431.01 Update 3
- HoloLens 模拟器 10.0.14393.0
- Unity 5.5.0f3 个人版(64 位)
创建 UWP DLL:
为了解决这个问题,我在Visual Studio 2015中创建了一个C++ DLL(Windows Universal),如下所示:
新项目 > Visual C++ > Windows > Universal > DLL(通用 Windows)
自动生成项目后,我添加了代码。 因此,代码如下所示:
本机库代码:
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 文件的位置现在是:项目根文件夹/发布/简单项目/简单项目DLL.dll。
---------------------
下一步,我创建了一个新的 Unity 项目,添加了 HoloLens-Toolkit,并确保新项目在模拟器上运行良好。
Unity项目代码:
之后,我在资产文件夹中添加了 SimpleProjectDLL.dll 并实现了以下代码:
首先,我们需要在委托之间建立连接。 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 仿真器”启动它,我会得到以下输出:
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”呼叫对话,标头使用“C”呼叫会话。
您应该通过删除来更改 SimpleProjectDLL.cpp
typedef void(*CB_V)();
typedef void(*CB_V_VI)(const char * a, int b);
并添加
#include "SimpleProjectDLL.h"
评论