为Unity构建C ++插件
试图创建我的第一个插件。 cpp代码是:
标题:
#pragma once #ifndef __MY_DLL_H #define __MY_DLL_H extern "C" int add_1(int number); #endif
资源:
//FirstDLL.cpp #include "FirstDLL.h" extern "C" int add_1(int number) { return number + 1; }
然后我编译并将DLL放在Assets/Plugins
文件夹中,dll文件是FirstDLL.dll
。 从统一方面来说,我有一个简单的C#脚本用于组件:
using UnityEngine; public class MyBehaviour : MonoBehaviour { // Use this for initialization [Header("Nuts!")] public int my_curr_val; void Start () { } // Update is called once per frame void Update () { print(add_1(my_curr_val)); } [DllImport("FirstDLL")] public static extern int add_1(int number); }
但是当我尝试运行脚本时,我收到以下错误:
插件:无法加载’Assets / Plugins / FirstDLL.dll’并显示错误’此操作仅在应用程序容器的上下文中有效。 ”。 插件:无法加载’Assets / Plugins / FirstDLL.dll’并显示错误’此操作仅在应用程序容器的上下文中有效。 ”。 DllNotFoundException:FirstDLL MyBehaviour.Update()(在Assets / MyBehaviour.cs:17)
文档似乎很差,有什么建议吗? 有这个答案 ,但不确定我做错了什么。 我试图创建几个解决方案(Windows通用平台,Windows 8.1等)仍然无法正常工作。
您正在尝试在非UWP环境中加载UWP插件,这是因为您构建dll的方式。
这篇文章描述了如何在Unity中创建,编译和构建C ++插件。
用于此的软件版本(也适用于其他旧版本。提及此信息以防将来有更新和不同的UI):
-
Microsoft Visual Studio 2015
-
Unity 2017.2.0f3
1.转到文件 —> 新建 —> 项目……
2 。 转到Installed – > Templates —> Visual C ++,然后转到Win32控制台应用程序 。 键入项目的名称,然后单击“确定”。
3.单击“ 下一步”而不是“ 完成” :
4.选择DLL并取消选择Precompiled header,然后单击finish:
5.您现在可以创建源(.cpp)和标题(.h)文件。
A .。创建源文件:
这应该放在Source Files文件夹中。 右键单击Source Files —> Add —> New Item …
B.选择 C ++文件(.cpp),键入文件“FirstDLL.cpp”的名称,然后单击“添加”。
示例C ++测试源:
#include "FirstDLL.h" int add(int num1, int num2) { return num1 + num2; } int multiply(int num1, int num2) { return num1 * num2; } int substract(int num1, int num2) { return num1 - num2; } int divide(int num1, int num2) { return num1 / num2; }
A .。创建头文件:
这应该放在Header Files文件夹中。 右键单击Header Files —> Add —> New Item …
B.选择 头文件(.h) ,键入文件名“FirstDLL.h”,然后单击“添加”。
示例对应标题:
#ifndef FIRSTDLL_NATIVE_LIB_H #define FIRSTDLL_NATIVE_LIB_H #define DLLExport __declspec(dllexport) extern "C" { DLLExport int add(int num1, int num2); DLLExport int multiply(int num1, int num2); DLLExport int substract(int num1, int num2); DLLExport int divide(int num1, int num2); } #endif
而已。 您现在可以在那里编写C ++插件代码。
6.确保将构建版本设置为释放,将平台设置为64位
如果使用32位,请将平台设置为x86。
7 。 构建插件:
转到Build —> Build Solution
8 。 导入Unity:
PC,Mac和Linux独立版 :
将64位DLL文件放入Assets/Plugins
文件夹。
如果你只想支持32位,那么把插件放在Assets/Plugins/x86
。
如果要支持通用(32位和64位平台),请构建dll并将其放在Assets/Plugins/x86_64
文件夹中。
Android :
可以从Android Studio构建。
要从Visual Studio构建:
A.转到文件 —> 新建 —> 项目……
B。 转到已安装 – > 模板 —> Visual C ++然后跨平台 。 单击“ 安装Android支持C ++(更新x)” 。 然后按照指示安装它。
C. 转到已安装 – > 模板 —> Visual C ++ —> 跨平台 。 Android 。 选择Dynamic Shard Library(Android),然后键入项目名称并单击Ok。 现在,您可以跳回到步骤#5继续使用C ++进行编码。
将Android插件文件(不是dll)放入Assets/Plugins/Android
文件夹中。 支持的C ++插件扩展名.so
。
注意 :如果Android插件的名称是libFirstDLL-lib.so
,则在从C#引用它时删除lib
前缀和.so
。在这种情况下,它将是[DllImport("FirstDLL-lib")]
不像它本来应该是#9。
如果您同时拥有armeabi-v7a
和x86
Android .so
插件,则将它们分别放在Assets\Plugins\Android\libs\armeabi-v7a
和Assets\Plugins\Android\libs\x86
文件夹中。
iOS版
可以从Xcode构建,也可以将源文件包含在Unity中。 您也可以使用Visual Studio创建它。 只需按照上面的Android步骤操作,但这次使用安装iOS支持C ++(更新x)而不是安装Android支持C ++(更新x) 。 请注意,您需要使用Mac计算机为iOS构建或使用虚拟机。 完成此操作后,请按照此 Microsoft指令完成设置,以便Visual Studio可以在Mac OS上进行通信并构建项目。
将iOS插件文件(而不是DLL)放入Assets/Plugins/iOS
文件夹中。 支持的插件扩展名为.a
, .m
, .mm
, .c
, .cpp
。
必须使用[DllImport ("__Internal")]
而不是[DllImport("PluginName")]
或[DllImport("FirstDLL")]
如下面#9所示 。
9 。 从Unity / C#调用C ++函数 :
[DllImport("FirstDLL")] public static extern int add(int num1, int num2); [DllImport("FirstDLL")] public static extern int multiply(int num1, int num2); [DllImport("FirstDLL")] public static extern int substract(int num1, int num2); [DllImport("FirstDLL")] public static extern int divide(int num1, int num2); void Start() { Debug.Log("Add: " + add(10, 2)); Debug.Log("Multiply: " + multiply(10, 2)); Debug.Log("Substract: " + substract(10, 2)); Debug.Log("Divide: " + divide(10, 2)); }
输出 :
10 。 故障排除插件错误:
1.获取错误:
DllNotFoundException:
解决方案1 :
DllImport
中指定的DLL的名称与Dll名称不匹配。 通过重命名确保它们匹配,然后重新启动Unity。
解决方案2 :
DLL放在错误的文件夹中。 该文件夹必须命名为Assets/Plugins
。 拼写也区分大小写。
2.获取错误:
EntryPointNotFoundException:
解决方案1 :
声明为DllImport
的函数名称不存在或与C ++端声明的函数名称匹配。 确保双方的拼写相同。 拼写也区分大小写。
解决方案2 :
C ++ DLL函数未包含在C ++插件中。 在Windows上, dllexport
用于使这些函数在DLL中自行导出。 其他平台或操作系统不需要这样做。 这通常在头文件中完成,只是为了保持源文件的清洁。 请参阅上面的头文件中的示例或下面的屏幕截图。
解决方案3 :
您的编译器正在重命名C ++函数。 您可以通过使用extern
关键字将它们括起来来防止这种情况。 再次,请参阅上面的头文件中的示例或下面的屏幕截图:
2.没有错误但是错误或有线结果:
解决方案1 :
参数不匹配。 确保C ++和C#端的函数参数匹配并具有相同数量的参数。 数据类型也必须匹配。 如果他们不这样做,期望未定义的行为。