为Unity构建C++插件

12

尝试创建我的第一个插件。 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。从Unity侧面来看,我有一个简单的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”。 DllNotFoundException:FirstDLL MyBehaviour.Update()(位于Assets/MyBehaviour.cs:17)
文档似乎相当贫乏,有什么建议吗? 有这个答案,但不确定我做错了什么。我尝试创建几个解决方案(Windows通用平台、Windows 8.1等),仍然无法正常工作。

1
但是文档上说“Assets/Plugins”,为什么我要把它放在那里?(顺便试过了,没有任何区别)。 - user8469759
实际上我在谈论Unity中的平台设置。文件-->构建设置 - Programmer
它被设置为“Android”。 - user8469759
将Unity平台切换到“PC,Mac和Linux独立版”,然后查看问题是否仍然存在。顺便问一下,您想使用此插件针对哪个平台? - Programmer
1
很少有人像你这样给我这么好的答案。谢谢你。 - user8469759
显示剩余5条评论
1个回答

44
你正在尝试在非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并取消选择预编译头文件,然后点击完成:

enter image description here

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

A.创建源文件:

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

enter image description here

B.选择C++文件(.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;
}

A.创建一个头文件:

这应该放在头文件文件夹中。右键单击“头文件”--->“添加”--->“新项目…”

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

enter image description here

如果使用32位系统,请将平台设置为x86。
7.构建插件:
进入“生成”--->“生成解决方案”。

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构建:

A.转到文件 ---> 新建 ---> 项目...

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

enter image description here

C. 进入 已安装 --> 模板 ---> Visual C++ ---> Cross Platform,然后选择 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步骤进行操作,但这次使用Install iOS support for C++ (Update x)而不是Install Android support for C++ (Update x)。请注意,您需要Mac电脑才能为iOS构建或使用虚拟机。完成此操作后,请遵循thisMicrosoft说明完成设置,以便Visual Studio可以与您的Mac OS通信并构建项目。
将iOS插件文件(不是dll)放入Assets/Plugins/iOS文件夹中。支持的插件扩展名为.a.m.mm.c.cpp
必须使用[DllImport("__Internal")]而不是[DllImport("PluginName")][DllImport("FirstDLL")],如下所示#99从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


嗨,在Visual Studio中创建Android共享库项目时,应该创建什么样的项目? - user8469759
请查看我在答案中更新的Android部分。我过去使用Android Studio,但后来尝试了VS15并且它可以工作。我已经更新了Android的VS15指令。 - Programmer
2
只是为了赞扬你的回答而复活,感谢你的努力 @程序员 - Zorkind
我有一个问题,是否可能在Unity之外的预编译游戏中连接本地插件?我拥有游戏的C#项目,因此可以很好地构建Assembly-CSharp.dll,并将其覆盖原始游戏dll,但我的问题是游戏忽略了本地插件。是否有任何方法可以进行链接并实现Unity构建游戏时所做的链接? - Zorkind

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接