# 前言

上一篇尝试将 Hololens2 的研究模式与 Unity 项目进行了整合。归根结底,就是将研究模式的相关 API(C++)构建成 DLL 文件,才能实现在 Unity(C#)中进行调用。这篇就介绍一下如何自己创建一个最简单的 DLL 文件,实现在 Unity 中的调用。

# 环境

  • Windows 10 教育版 18363.1379
  • Unity 2019.4.20f1c1
  • VS2019 16.8.6
  • WIN SDK 10.0.18362.0
  • Hololens2 内部预览版本 10.0.20301.1000

# VS2019 创建 DLL 项目

选择创建新项目,搜索 DLL 模板,选择 DLL(通用Windows) 模板,点击下一步

设置项目名称和位置,点击创建

选择目标版本最低版本,一般默认即可。实际上,项目创建完成后,在项目属性设置中也可更改这个设置,如何更改可以看:Hololens2 - 运行研究模式官方案例(SensorVisualization)

# 编写 DLL 代码

主要更改的就是 HL2RmUnityPlugin.hHL2RmUnityPlugin.cpp 这两个文件。编写代码如下

HL2RmUnityPlugin.h

#pragma once

#define FUNCTIONS_EXPORTS_API extern "C" __declspec(dllexport)

extern "C" {
	typedef struct IMUInputForUnity {
		double x;
		double y;
		double z;
	}INPUT;

	typedef struct IMUOutputForUnity {
		double x;
		double y;
		double z;
	}OUTPUT;
}

namespace HL2Stream {

	FUNCTIONS_EXPORTS_API int __stdcall GetIMUStreaming(INPUT* input, OUTPUT* output);

}

HL2RmUnityPlugin.cpp

#include "pch.h"
#include "HL2RmUnityPlugin.h"

int __stdcall HL2Stream::GetIMUStreaming(INPUT* input, OUTPUT* output)
{
	output->x = input->x * input->x;
	output->y = input->y * input->y;
	output->z = input->z * input->z;
	return 200;
}

GetIMUStreaming 函数接收两个结构体作为参数,返回 int 类型表示执行结果。

# 生成 DLL 文件

因为最终 Unity 项目要部署到 Hololens2 上,所以这里构建方式选择 Release ARM64 。点击菜单栏生成 -> 生成解决方案。成功后即可在项目目录下找到 ARM64\Release\HL2RmUnityPlugin\HL2RmUnityPlugin.dll 文件了。

# Unity 调用 DLL

把 dll 文件拷贝到 Unity 项目的 Assets\Plugins\HL2RmStream 目录下,目录不存在就创建。然后在 Assets\Scripts 目录下创建一个 C# 脚本,编写如下:

using System;
using System.Runtime.InteropServices;
using TMPro;
using UnityEngine;
public class GetTime : MonoBehaviour
{
    [StructLayout(LayoutKind.Sequential)]
    struct INPUT
    {
        public double x;
        public double y;
        public double z;
    };
    [StructLayout(LayoutKind.Sequential)]
    struct OUTPUT
    {
        public double x;
        public double y;
        public double z;
    }
#if ENABLE_WINMD_SUPPORT
    [DllImport("HL2RmUnityPlugin", EntryPoint = "GetIMUStreaming", CallingConvention = CallingConvention.StdCall)]
    public static extern int GetIMUStreaming(IntPtr pv1, IntPtr pv2);
#endif
    public TextMeshPro textMeshPro;
    private void Start()
    {
#if ENABLE_WINMD_SUPPORT
        INPUT pIn = new INPUT();
        pIn.x = 1.0;
        pIn.y = 2.0;
        pIn.z = 3.0;
        int sizeIn = Marshal.SizeOf(typeof(INPUT));
        IntPtr pBuffIn = Marshal.AllocHGlobal(sizeIn);
        Marshal.StructureToPtr(pIn, pBuffIn, true);
        int sizeOut = Marshal.SizeOf(typeof(OUTPUT));
        IntPtr pBuffOut = Marshal.AllocHGlobal(sizeOut);
        int result = GetIMUStreaming(pBuffIn, pBuffOut);
        OUTPUT pOut = (OUTPUT)Marshal.PtrToStructure(pBuffOut, typeof(OUTPUT));
        textMeshPro.text = $"{pOut.x} {pOut.y} {pOut.z}";
#endif
    }
}

C# 需要将结构体转为指针进行调用。为了能看到运行结果,创建一个 TextMeshPro 对象挂载到这个脚本时来显示运行结果。

# 部署到 Hololens 上

因为 Windows 机器不能运行 ARM64 的程序,所以只能把 Unity 项目构建部署到 Hololens 上运行即可~

部署相关操作看之前的文章吧,这里不在赘述了。接下来来好好的捣鼓捣鼓 Hololens 的研究模式吧~

# 参考

Unity3D 中调用 C++ 动态链接库 (dll)- 两种方式 (Managed Plugins 和 Native Plugins)

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

宇凌喵 微信支付

微信支付

宇凌喵 支付宝

支付宝