【发布时间】:2017-03-25 13:46:30
【问题描述】:
我正在 Unity3D 上开发基于 Kinect 的手势识别应用程序。我必须使用已经用 Matlab 编写的算法。因此,我决定使用 Matlab deploytool 生成一个 .Net DLL,并且我成功地做到了。然后我在一个独立的 .Net 应用程序项目(在 Visual Studio 2017 中)中测试了 DLL,它运行良好。但是,当我转向 Unity3D 时,那个 DLL 从来没有工作过......我得到的如下所示: enter image description here
System.TypeInitializationException: An exception was thrown by the type initializer for Untitled1.ADD ---> System.NotImplementedException: The requested feature is not implemented.
at System.Security.Principal.WindowsIdentity.GetCurrent (Boolean ifImpersonating) [0x00000] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Security.Principal/WindowsIdentity.cs:166
at MathWorks.MATLAB.NET.Utility.MWMCR.EvaluateFunction (System.String functionName, Int32 numArgsOut, Int32 numArgsIn, MathWorks.MATLAB.NET.Arrays.MWArray[] argsIn) [0x00000] in <filename unknown>:0
at MathWorks.MATLAB.NET.Utility.MWMCR.EvaluateFunction (Int32 numArgsOut, System.String functionName, MathWorks.MATLAB.NET.Arrays.MWArray[] argsIn) [0x00000] in <filename unknown>:0
at MathWorks.MATLAB.NET.Utility.MWMCR.setBuilderUserData () [0x00000] in <filename unknown>:0
at MathWorks.MATLAB.NET.Utility.MWMCR..ctor (System.String componentId, System.String componentPath, System.IO.Stream embeddedCtfStream, Boolean isLibrary) [0x00000] in <filename unknown>:0
at Untitled1.ADD..cctor () [0x00000] in <filename unknown>:0
--- End of inner exception stack trace ---
at dlltest.Start () [0x00000] in E:\Unity\mPrj\Assets\dlltest.cs:40
UnityEngine.Debug:Log(Object)
dlltest:Start() (at Assets/dlltest.cs:46)
从日志看,好像是初始化MCR失败了,但是看了Matlab生成的C#源代码后我就是不知道为什么(以前做过这个工作的人一定知道我在说什么)。 有没有人在这种工作方面经验丰富,可以向我解释发生了这种情况以及如何解决?非常感谢!
DLL 的命名空间是Untitled1(来不及给它起个名字...),DLL 中的类的名称是ADD。 以下是此过程中的相关代码(测试样例):
matlab源代码add.m:
function y = add(n,m)
y = n+m;
Matlab在将M文件构建成DLL时生成的C#代码太长,这里就不贴了,所以我只展示定义构造函数的代码,根据Log,Unity3D中出现错误:
static ADD()
{
if (MWMCR.MCRAppInitialized)
{
Assembly assembly= Assembly.GetExecutingAssembly();
string ctfFilePath= assembly.Location;
int lastDelimiter= ctfFilePath.LastIndexOf(@"\");
ctfFilePath= ctfFilePath.Remove(lastDelimiter, (ctfFilePath.Length - lastDelimiter));
string ctfFileName = "Untitled1.ctf";
Stream embeddedCtfStream = null;
String[] resourceStrings = assembly.GetManifestResourceNames();
foreach (String name in resourceStrings)
{
if (name.Contains(ctfFileName))
{
embeddedCtfStream = assembly.GetManifestResourceStream(name);
break;
}
}
mcr= new MWMCR("",
ctfFilePath, embeddedCtfStream, true);
}
else
{
throw new ApplicationException("MWArray assembly could not be initialized");
}
}
在独立 .Net 应用程序中成功使用 DLL 的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathWorks.MATLAB.NET.Utility;
using MathWorks.MATLAB.NET.Arrays;
using Untitled1;
namespace AddDllTest
{
class Program
{
static void Main(string[] args)
{
ADD myAdd = new ADD();
Console.WriteLine(myAdd.add((MWArray)1, (MWArray)1));
}
}
}
还有代码是Unity3D脚本,在Unity3D中无法使用DLL(部分cmets已被删除):
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
using RootSystem = System;
using System;
using System.Reflection;
using System.IO;
using Untitled1;
using MathWorks.MATLAB.NET.Arrays;
using MathWorks.MATLAB.NET.Utility;
public class dlltest : MonoBehaviour {
MWArray test1 = 1;
MWArray ref0 = 2;
MWArray result;
ADD myADD;
//Use this for initializations
void Start () {
try
{
myADD = new ADD();
}
catch (Exception e)
{
Debug.Log("EXCEPTION");
Debug.Log(e.ToString());
}
}
// Update is called once per frame
void Update () {
result = myADD.add(test1,ref0);
Debug.Log(result);
}
}
【问题讨论】: