c# - 为Unity构建C++插件

标签 c# c++ unity3d dll

尝试创建我的第一个插件。
cpp代码为:

header :

#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);
}

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

Plugins: Failed to load 'Assets/Plugins/FirstDLL.dll' with error 'This operation is only valid in the context of an app container. '. Plugins: Failed to load 'Assets/Plugins/FirstDLL.dll' with error 'This operation is only valid in the context of an app container. '. DllNotFoundException: FirstDLL MyBehaviour.Update () (at Assets/MyBehaviour.cs:17)



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

最佳答案

您正在尝试在非UWP环境中加载UWP插件,这是由于生成dll的方式所致。

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

用于此目的的软件版本(也应适用于其他较旧的版本。仅在将来有更新和不同的UI时提及此信息):

  • Microsoft Visual Studio 2015
  • Unity 2017.2.0f3

  • 1 。转到文件--->新建--->项目...

    enter image description here

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

    enter image description here

    3 。单击下一步而不是完成:

    enter image description here

    4 。选择DLL并取消选择Precompiled header ,然后单击完成:

    enter image description here

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

    一个创建一个源文件:

    这应该放在源文件文件夹中。右键单击源文件--->添加--->新建项目...

    enter image description here

    B 。选择C++ File(.cpp),键入文件“FirstDLL.cpp”的名称,然后单击“添加”。

    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;
    }
    

    一个创建一个头文件:

    这应该放在 header 文件文件夹中。右键单击头文件--->添加--->新建项目...

    enter image description here

    B 。选择头文件(.h),键入文件“FirstDLL.h”的名称,然后单击“添加”。

    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 。确保将构建版本设置为release,平台设置为64位

    enter image description here

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

    7 .Building插件:

    转到构建--->构建解决方案

    enter image description here

    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生成:

    一个。转到文件--->新建--->项目...

    B 。转到已安装->模板---> Visual C++,然后跨平台。单击“安装Android对C++的支持(更新x)”。然后按照说明进行安装。

    enter image description here

    C 。转到已安装->模板---> Visual C++ --->跨平台。然后是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

    关于c# - 为Unity构建C++插件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49793560/

    相关文章:

    c# - 两个网格单元之间的距离,没有对角线

    c# - 跨线程操作对于使图形对象无效无效

    c# - 使此 C# SwapBytes 代码与 x64 兼容

    c++ - 用于编译多个 mex 函数的 Makefile

    c++ - 在 C++ 中使用指针列表,(继承还是性能?)

    c# - 使用新的 Unity 5.1 传输层 API 流式传输 WebCamTexture

    C# 接口(interface)对象列表 - 类型转换单个元素

    c++ - 在映射最小值和最大值时从无符号转换为有符号的最佳方法?

    android - 统一安卓 : How to preload scenes in cache

    c# - 统一健康和装甲