为Unity构建C ++插件

时间:2018-04-12 09:56:54

标签: c# c++ unity3d dll

尝试创建我的第一个插件。 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);
}

但是当我尝试运行脚本时,我收到以下错误:

  

插件:无法加载'资产/插件/ FirstDLL.dll'有错误   '此操作仅在应用容器的上下文中有效。       &#39 ;.       插件:无法加载'资产/插件/ FirstDLL.dll'错误'此操作仅在应用容器的上下文中有效。       &#39 ;.       DllNotFoundException:FirstDLL       MyBehaviour.Update()(在Assets / MyBehaviour.cs:17)

文档似乎很差,有什么建议吗? 有this answer,但不确定我做错了什么。我试图创建几个解决方案(Windows通用平台,Windows 8.1等)仍然无法正常工作。

1 个答案:

答案 0 :(得分:7)

您正在尝试在非UWP环境中加载UWP插件,这是因为您构建dll的方式。

这篇文章描述了如何在Unity中创建,编译和构建C ++插件。

用于此目的的软件版本(也适用于其他旧版本。如果将来有更新和不同的用户界面,则会提及此信息):

  • Microsoft Visual Studio 2015

  • Unity 2017.2.0f3

1 。转到文件 ---> ---> 项目...

enter image description here

<强> 2 即可。转到已安装 - &gt; 模板 ---&gt; Visual C ++ 然后 Win32控制台应用程序。输入项目名称,然后单击“确定”。

enter image description here

3 。点击下一步而不是完成

enter image description here

4 。选择 DLL 并取消选择预编译标题,然后点击完成:

enter image description here

5 。您现在可以创建源(.cpp)和标题(.h)文件。

A 。创建源文件:

这应该放在源文件文件夹中。右键单击Source Files ---&gt;添加---&GT;新项目......

enter image description here

B 。选择C ++文件(.cpp),输入文件的名称&#34; FirstDLL.cpp&#34;然后单击添加。

enter image description here

示例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 ---&gt;添加---&GT;新项目......

enter image description here

B 。选择头文件(.h),输入文件的名称&#34; FirstDLL.h&#34;然后单击添加。

enter image description here

示例相应的标题:

#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位

enter image description here

如果使用32位,请将平台设置为x86。

7 构建插件:

转到构建 ---&gt; 构建解决方案

enter image description here

8 导入Unity:

PC,Mac&amp; Linux Standalone

将64位dll文件放入Assets/Plugins文件夹。

如果您只想支持32位,请将插件放入Assets/Plugins/x86

如果要支持通用(32位和64位平台),请构建dll并将其放在Assets/Plugins/x86_64文件夹中。

<强>的Android

可以从 Android Studio 构建。

从Visual Studio构建:

A 。转到文件 ---&gt; ---&gt; 项目...

<强>乙即可。转到已安装 - &gt; 模板 ---&gt; Visual C ++ 然后跨平台。单击安装Android支持C ++(更新x)。然后按照指示安装它。

enter image description here

<强> C 即可。转到已安装 - &gt; 模板 ---&gt; Visual C ++ ---&gt; 跨平台。然后 Android 。选择动态分片库(Android),然后键入项目名称,然后单击“确定”。现在,您可以跳回到步骤#5 继续使用C ++进行编码。

enter image description here

将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构建或使用虚拟机。完成此操作后,请按照this 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));
}

<强>输出

enter image description here

10 疑难解答插件错误:

1 。获取错误:

  

DllNotFoundException:

enter image description here

解决方案1 ​​

DllImport中指定的DLL名称与Dll名称不匹配。通过重命名确保它们匹配,然后重新启动Unity。

enter image description here

解决方案2

DLL放在错误的文件夹中。该文件夹必须命名为Assets/Plugins。拼写也区分大小写。

enter image description here

2 。获取错误:

  

EntryPointNotFoundException:

enter image description here

解决方案1 ​​

声明为DllImport的函数名称不存在或与C ++端声明的函数名称匹配。确保双方的拼写相同。拼写也区分大小写。

enter image description here

解决方案2

C ++ DLL函数未包含在C ++插件中。在Windows上,dllexport用于使这些函数在DLL中自行导出。在其他平台或操作系统中不需要这样做。这通常在头文件中完成,只是为了保持源文件的清洁。请参阅上面的头文件中的示例或下面的屏幕截图。

enter image description here

解决方案3

您的编译器正在重命名C ++函数。您可以使用extern关键字将其括起来以防止这种情况发生。再次,请参阅上面的头文件中的示例或下面的屏幕截图:

enter image description here

2 。没有错误但是错误或有线结果:

enter image description here

解决方案1 ​​

参数不匹配。确保C ++和C#端的函数参数匹配并具有相同数量的参数。数据类型也必须匹配。如果他们不这样做,则期待未定义的行为。

enter image description here