Обратные вызовы HoloLens с собственной библиотекой
Моя цель - вызвать методы, которые реализованы в Unity Code, из моей библиотеки UWP. (Так что я могу использовать их в своем проекте HoloLens)
Я попробовал это с большим проектом, но потерпел неудачу. Поэтому я написал простой пример, чтобы упростить поиск ошибки и исключить другие влияния. Но все равно я получаю ту же ошибку.
Моя рабочая среда:
- 64-битный компьютер с ОС Windows 10
- Micsrosoft Visual Studio Community 2015 версия 14.0.25431.01 обновление 3
- HoloLens Emulator 10.0.14393.0
- Unity 5.5.0f3 Personal (64 бит)
Создание UWP DLL:
Чтобы приблизиться к этому, я создал C++ DLL(Windows Universal) в Visual Studio 2015 следующим образом:
Новый проект> Visual C++ > Windows > Universal > DLL(Universal 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.
Наконец я строю проект для режима "Release" и архитектуру "x86" для генерации DLL-файла. Расположение DLL-файла теперь: project-root-folder / Release / SimpleProject / SimpleProjectDLL.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, та же проблема, так что проблема не лежит в эмуляторе.
0 ответов
Ошибка 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"