【问题标题】:Loading a native C++ dll generated from MATLAB(Simulink) into Unity3d将从 MATLAB(Simulink) 生成的本机 C++ dll 加载到 Unity3d
【发布时间】:2013-12-02 23:38:48
【问题描述】:

我是一名开发严肃游戏的游戏开发者。由于 MATLAB (Simulink) 模型,我进行了一些数据模拟,该模型是由现在离开团队的人创建的。所有这些数据模拟都会生成有用的数据,并允许我在需要时查询和检查变量。我需要使用此模型构建游戏。所以我使用 Simulink 代码生成器在 C++ 中为我的模型生成代码。这是本机 C++ 并且是程序性的。我重写它的代码量很大,因此我避免这样做。我需要在我正在开发游戏的引擎 Unity3d 中使用此代码。

长话短说。我需要在 Unity3d 中加载本机 C++ dll(由 Simulink 生成)。

我尝试了什么:

  1. 我尝试使用 Unity3d 的原生插件 API。我有专业版,它似乎没有检测到 dll,只是抛出异常。我正在使用 extern 关键字公开所需的变量,但仍然没有运气。

  2. 我尝试按照本教程 (http://blogs.abo.fi/alexeevpetr/2011/11/18/simplified-building-simulink-generated-c-code-in-visual-studio/) 进行操作,但它会引发错误并且无法构建,这可能是因为 MATLAB 的版本。

  3. 我也考虑过使用包装器,但这意味着我要重新重写大部分代码。

【问题讨论】:

  • 我从未尝试过,但我的理解是 MATLAB 提供了 mex 作为 MATLAB 运行时库和编译器之间的包装,因此使用 mex 生成的编译对象不仅包含标准 C++但它是“你的代码 + matlab 库”,它仍然需要 MATLAB 运行时库才能运行。此外,许可您的代码也可能存在问题,因为只有购买 MATLAB 的用户才能合法地运行您的代码。
  • 我知道 MATLAB 提供了 mex,但是当我在 VS2010 中打开项目时,VS2010 并没有说该项目链接到任何 MATLAB 文件。 MATLAB 被许可在我的用户帐户上运行,所以我忽略了这一点。
  • Simulink Coder 生成独立代码,它不包含任何 MATLAB 库的链接,因此 @user2485710 的注释与此处无关。您正在使用什么代码生成目标?唯一自动生成 dll 的是 Embedded Coder 中的 ertdll 目标。您是使用它,还是仅使用标准 Simulink Coder 生成 C++ 代码,然后自己编译成 dll?
  • @PhilGoddard 我可以很容易地接受我在这方面错了的事实,但是,如果 SL 使用任何 C++ 标准生成 C++ 代码(显然没有来自 Mathworks 的话),那有什么意义呢? mex ?
  • 这里没有足够的篇幅来详细描述这些,但是:mex(MATLAB 可执行文件)是编译 C/C++/Fortran 代码的机制,因此可以从 MATLAB 中调用它; MATLAB Coder 是一个将 m 代码(不是 Simulink)转换为完全独立于 MATLAB 的 C 代码的工具; MATLAB Compiler 是将 m 代码(不是 Simulink)转换为完全依赖于 MATLAB 引擎的应用程序的工具; Simulunk Coder 是将 Simulink 模型(不是 MATLAB)转换为独立于 MATLAB 或 Simulink 的 C 代码的工具

标签: c++ dll unity3d native simulink


【解决方案1】:

我从未在 Unity 中使用过本机 dll,但我猜您总是可以尝试几种代码桥接方法之一来从 C# 调用 C++ 代码。那么如何编写一个 C++/CLI 包装器呢?它不会强迫你重写任何东西。它提供对非托管代码的托管访问权限,无论如何它都是一种有用的学习技术。

【讨论】:

  • C# 只能用 C 扩展,不能用 C++ 扩展,你的回答更像是评论。
  • 嗯?你是什​​么意思“用C扩展”?您可以编写 C++/CLI 包装器代码并编组您的数据类型以在 C# 代码中使用,当然可以。
  • FFI 机制基于 C 代码,C# 可以与任何可以翻译成 C 代码的语言进行通信,您生成和使用的“dll”基本上是一个 C 库。规范中没有任何其他内容告诉您,即使是其他语言使用其他 FFI 的经验,如果您仔细阅读所有这些示例,没有什么是真正的 C++-ish,有很多非常基本的数据结构和指针,这是一个提示...
  • 但是对于那些不担心幕后发生的事情的人来说,您正在重用 C++ 代码,无论其机制是否是 C。我的观点是他(或她)不必重写所有内容。
  • 假设您可以在这方面作弊,C 甚至是 C++ 标准的一部分,因此您可以这样说而不会陷入难题,但我的意思是:请注意这一点,如果您处理一些“真实的”C++ 代码,例如std::vector,确保您知道自己在做什么以及如何将 C++ 向量移植到 C 代码中。
【解决方案2】:

您应该能够将您的原生插件加载到 Unity3D 中,即使它需要 MATLAB 库(只要确保它们也在 plugins 目录中)。我最近回答了一个类似的问题,因为要正确可能相当棘手。我建议您查看HERE,并使用您在尝试加载本机代码时遇到的特定错误和问题修改您的问题。

【讨论】:

  • 技术上确实如此,但“MATLAB 库”本质上需要一个巨大的运行时引擎,OP 很可能对与他们的产品一起发布不感兴趣。
【解决方案3】:

来自 U3d 论坛上的 Geomorillo:

在任何事情之前, 1)安装Visual C++ Studio Express 2010,我们需要.NET的sdk进行编译,(注意:也许你可以使用visual C# express来代替编译,因为它需要.NET sdk但不确定) 2)必须使用命令“mbuild - setup”设置matlab,并选择编译器Microsoft Visual C++ Studio Express 2010 3) 你必须已经创建了一个函数并将其保存到一个“.m”文件中,我的文件名为 mycos.m,其内容如下:

函数 a=mycos(b) a=cosd(b); 结束

其中“a”是返回参数,“b”是输入参数,重要的是要知道在这种情况下您有多少个返回参数 1(参见步骤 12)

4) 使用“deploytool”命令,应该会打开一个窗口,将项目命名为“simplelibs”,任何名称都可以,选择位置 c:\matlab\simplelib,在类型中选择 .NET Assembly,OK 5) 之后,选项卡形式的新选项应出现在窗口右侧,即 Build 和 Package 选项卡。 在 Build 选项卡中,您应该使用 Add class 选项添加一个类,它将自动命名为 Class1,但我将其更改为 Myclass,在这里您可以使用 Add files 将您的函数添加到您的类中,我添加了 mycos.m 6)您应该注意到项目名称旁边的 3 个按钮,单击带有螺母形状的第 3 个按钮,转到设置应该会出现一个新窗口,转到 .NET 选项卡并在 Microsoft Framework 中选择 3.5 以确保您正在使用 .net 3.5 进行编译(unity3d 需要) 7)我们准备好编译了,用第一个按钮编译,它应该需要一段时间...... 8)编译无误后,文件在你的工程路径下的distrib文件夹下,打开unity,新建一个工程。将 2 个 dll 复制到统一的根目录中。 9)在“c/.../matlab/../toolbox”中找到de目录“dotnetbuilder”,将其所有内容复制或拖动到您的统一项目中。

10) 我们需要一个 dll MWArray.dll,因为在编译我们的库时,matlab 将我们的函数包装在一个数组中,并且它使用它的方法来访问我们的函数我不会解释这个,请谷歌它,通常可以在里面找到matlab 安装 dotnetbuilder/bin/win32/2.0/ 但是由于您已将其复制到 unity 不要再次复制,当使用此 mwarray 时,我在此库中发现了 monodevelop 的错误,因此我必须对其进行反编译并修复我必须重新编译的错误再来一次 :) 你可以在这里下载这个文件https://dl.dropbox.com/u/6716823/MWArray.dll 并替换在统一项目中找到的那个(不要!!!从 matlab 目录中替换原始文件)

11) 创建一个 c# 脚本并将其分配给主摄像机或场景中的任何对象 这是它的内容

使用 UnityEngine; 使用 System.Collections; 使用系统; 使用 MathWorks.MATLAB.NET.Arrays; // 从 MWArray.dll 导入 使用simplelib;

公共课 myMatlab : MonoBehaviour {

无效开始(){ simplelib.Myclass g = new simplelib.Myclass(); Debug.Log(g.mycos(1,95).GetValue(0)); } }

12) g.mycos(1,95); // 记得我说过它包装了你的函数!!!第一个参数是从我们的 matlab 函数返回的参数数量,在这种情况下 1,95 是我们要发送给函数的参数,我们得到一个数组,我们可以使用 .GetValue(0) 访问它

13) 玩耍和享受

这是一个简单函数的例子,所以我不知道它是否适用于更复杂的程序

我希望这对你有用

【讨论】:

    猜你喜欢
    • 2016-08-15
    • 2017-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    相关资源
    最近更新 更多