Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build C++ plugin for Unity

Tags:

c++

c#

dll

unity3d

Trying to create my first plugin. The cpp code is:

header:

#pragma once
#ifndef __MY_DLL_H
#define __MY_DLL_H

extern "C" int add_1(int number);

#endif

source:

//FirstDLL.cpp
#include "FirstDLL.h"

extern "C" int add_1(int number) {
    return number + 1;
}

Then I compile and put the DLL in Assets/Plugins folder, the dll file is FirstDLL.dll. From the unity side I have a simple C# script for a component:

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

But when I try to run the script I get the following error:

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)

The documentation seems to be quite poor, any suggestions? There's this answer, but not sure what I'm doing wrong. I've tried to create several solution (windows universal platform, windows 8.1, etc) still doesn't work.

like image 661
user8469759 Avatar asked Apr 12 '18 09:04

user8469759


People also ask

Can I use C for Unity?

Unity supports the C# programming language natively. C# (pronounced C-sharp) is an industry-standard language similar to Java or C++. In addition to this, many other . NET languages can be used with Unity if they can compile a compatible DLL - see here for further details.

Is Unity C-sharp or C++?

Both Unity and UnrealEngine utilize C++ in their source code: Unity is partially written using C++ and C#, whereas Unreal Engine is written in C++ entirely. C++ is widely used to develop high-tier game engines and critical service applications where optimal resource utilization and performance are a priority.

Is C-sharp different in Unity?

The C# in unity is regular C#, just like you'd learn when studying for your MCPD. If you're used to . Net, you'll be right at home going straight into C# in Unity.


1 Answers

You are trying to load UWP plugin in a non UWP environment and this is because of the way you build your dll.

This post describes how to create, compile and build C++ plugin in Unity.

Software version used for this (should work for other older versions too. This information is mentioned just in case there is an update and different UI in the future):

  • Microsoft Visual Studio 2015

  • Unity 2017.2.0f3

1.Go to File ---> New ---> Project...

enter image description here

2. Go to Installed --> Templates ---> Visual C++ then Win32 Console Application. Type the name of the project then click Ok.

enter image description here

3.Click Next instead of Finish:

enter image description here

4.Select DLL and unselect Precompiled header then click finish:

enter image description here

5.You can now create your source(.cpp) and header(.h) files.

A.Create a source file:

This should be placed in the Source Files folder. Right click on Source Files ---> Add---> New Item...

enter image description here

B.Select C++ File(.cpp), type the name of the file "FirstDLL.cpp" then click Add.

enter image description here

Example C++ test source:

#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.Create a header file:

This should be placed in the Header Files folder. Right click on Header Files ---> Add---> New Item...

enter image description here

B.Select Header File(.h), type the name of the file "FirstDLL.h" then click Add.

enter image description here

Example corresponding header:

#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

That's it. You can now write your C++ plugins code there.

6.Make sure to set the build to release and the platform to 64 bit

enter image description here

If using 32-bit, set the platform to x86.

7.Building plugin:

Go to Build ---> Build Solution

enter image description here

8.Importing into Unity:

PC, Mac & Linux Standalone:

Put the 64-bit dll file into Assets/Plugins folder.

If you just want to support 32-bit then put the plugin in Assets/Plugins/x86.

If you want to support universal (both 32-bit and 64-bit platform) then build the dll as such and put it in the Assets/Plugins/x86_64 folder.

Android:

Can be build from Android Studio.

To build from Visual Studio:

A.Go to File ---> New ---> Project...

B. Go to Installed --> Templates ---> Visual C++ then Cross Platform. Click on Install Android support for C++ (Update x). then follow direction to install it.

enter image description here

C. Go to Installed --> Templates ---> Visual C++ ---> Cross Platform. then Android. Select Dynamic Shard Library (Android) then type the name of the project and click Ok. Now, you can jump back to step #5 to continue coding in C++.

enter image description here

Put the Android plugin file (not dll) into the Assets/Plugins/Android folder. The supported C++ plugin extension .so.

Note: If the name of the Android plugin is libFirstDLL-lib.so, remove the lib prefix and the .so when referencing it from C#.In this case, it would be [DllImport("FirstDLL-lib")]unlike what it would have been in #9.

If you have both armeabi-v7a and x86 Android .so plugins then put them in Assets\Plugins\Android\libs\armeabi-v7a and Assets\Plugins\Android\libs\x86 folders respectively.

iOS

Can be build from Xcode or include the source file into Unity. You can also create it with visual Studio too. Just follow the Android step above but use Install iOS support for C++ (Update x) this time instead of Install Android support for C++ (Update x). Note that you need Mac computer to build for iOS or use virtual machine. Once you do this, follow this Microsoft instruction to finish the setup so that Visual Studio can communicate and build the project on your Mac OS.

Put the iOS plugin file (not dll) into the Assets/Plugins/iOS folder. The supported plugins extension are .a, .m, .mm, .c, .cpp.

Must use [DllImport ("__Internal")] instead of [DllImport("PluginName")] or [DllImport("FirstDLL")] as seen below in #9.

9.Calling C++ function from Unity/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));
}

Output:

enter image description here


10.TROUBLESHOOTING PLUGIN ERRORS:

1.Getting the error:

DllNotFoundException:

enter image description here

Solution 1:

The name of the DLL specified in DllImport does not match the Dll name. Make sure they match by renaming them then restart Unity.

enter image description here

Solution 2:

The DLL is placed in the wrong folder. The folder must be named Assets/Plugins. The spelling is also case sensitive.

enter image description here


2.Getting the error:

EntryPointNotFoundException:

enter image description here

Solution 1:

The function name declared DllImport doesn't exist or match with the one declared on the C++ side. Make sure that the spellings are the-same on both sides. The spelling is also case sensitive.

enter image description here

Solution 2:

The C++ DLL functions are not being included in the C++ plugin. On Windows, dllexport is used to make these function export themselves in the DLL. This is not required in other platforms or OS. This is usually done in the header file only to keep the source file clean. See example in the header file above or screenshot below.

enter image description here

Solution 3:

You compiler is renaming the C++ functions. You can prevent this by enclosing them with the extern keyword. Again, see example in the header file above or screenshot below:

enter image description here

2.Getting no error but incorrect or wired result:

enter image description here

Solution 1:

The parameter doesn't match. Make sure that the parameter of the function on the C++ and C# side match and have the-same amount of parameter. Also the datatype must match. If they don't, expect undefined behavior.

enter image description here

like image 103
Programmer Avatar answered Nov 03 '22 09:11

Programmer