为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-v7ax86 Android .so插件,则将它们分别放在Assets\Plugins\Android\libs\armeabi-v7aAssets\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#端的函数参数匹配并具有相同数量的参数。 数据类型也必须匹配。 如果他们不这样做,期望未定义的行为。

在此处输入图像描述