Search Unity

Unity Personal Edition and Native Plugins

Discussion in 'General Discussion' started by UniteMage, Jan 9, 2022.

  1. UniteMage

    UniteMage

    Joined:
    Aug 22, 2012
    Posts:
    120
    I decided to post the question about Native Plugins here in the General Discussion forum. I could not find an appropriate forum discussing Native Platforms.

    Can I, when using Unity Personal Edition 2021.2.7, use Native Plugins?

    Thanks
     
  2. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,571
    All editions have the same feature set. Personal, Plus, Pro. The difference is ability to shut down splash screen and some extra services. So, yes, you should be able to. It is in the docs.

    https://docs.unity3d.com/2021.1/Documentation/Manual/NativePlugins.html
     
  3. UniteMage

    UniteMage

    Joined:
    Aug 22, 2012
    Posts:
    120
    Thanks for the quick reply....

    Although I did not explicitly asked the question, what forum would be best to discuss Native Plugins?
     
  4. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,571
    There's no dedicated forum for them. So, General SUpport or Scripting (because you need to write glue code) would PROBABLY be the best.
     
    zombiegorilla likes this.
  5. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    I'd say it depends on what kind of questions you have. Correctly defining function signatures for P/Invoke? Scripting forum. Doing something platform specific that interacts with the engine in the plugin? The platform in question forum.
     
  6. UniteMage

    UniteMage

    Joined:
    Aug 22, 2012
    Posts:
    120
    I always love these hints I get from Unity... Like function signatures for P/Invoke... The specific platform is MacOS but my ignorance on Frameworks and Bundles is right there on the bottom with the cherry pits.

    I am also a windows and Linux user... With that said, I would prefer the path of least resistance in setting-up a Native Plugin. The reason for the plugin is to incorporate C++ Large Math Library for the simulations. I thought at one time that Personal Unity did not allow for Native Plugins!?

    I was looking online for clean template like code and discovered that C# software that uses generics... I only found one but the code is incomplete.... https://github.com/HadiSalehWeb/LinearAlgebraSharp... The code is clean, once uploaded into unity and for days now trying to learn ADVANCED Csharp idiosyncrasies with frustrations...

    So my programming skills in Csharp although lacking, I was thinking of using a C++ Plugin for my work while using Unity...

    Thanks for the input...
     
  7. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Correct, before Unity 5. Since the release of Unity 5 in spring of 2015, we no longer have this limitation. Generally, using C++ code in Unity goes like this:

    1. Expose C++ functions you want to invoke from C# with export attribute:

    Code (csharp):
    1. #if defined(_MSC_VER)
    2. #define EXPORT extern "C" __declspec(dllexport)
    3. #else
    4. #define EXPORT extern "C" __attribute__ ((visibility ("default"))
    5. #endif
    6.  
    7. EXPORT int AddNumbers(int a, int b)
    8. {
    9.     return a + b;
    10. }
    2. Compile your C++ code into a native library (.dll/.dylib/.bundle/.so) using a C++ compiler or an IDE (Xcode, Visual Studio, etc).
    3. In C#, declare the functions you exported from your C++ library with [DllImportAttribute] (this is called a P/Invoke signature):

    Code (csharp):
    1. [DllImport("MyLibrary")]
    2. static extern int AddNumbers(int a, int b);
    4. Call that function as if it was a normal C# function.
     
    steril and karl_jones like this.
  8. UniteMage

    UniteMage

    Joined:
    Aug 22, 2012
    Posts:
    120
    So, IF I have very very large library (OOP) with classes having properties and methods instead of functions, then how is that exported? At the same time, just export what is needed and nothing more?

    The compiler macro (define) _MSC_VER stands for exactly what IDE?

    I really appreciate the help...

    Again Thanks

    Addendum:
    I am little confused as to where Unity is going with IL2CPP (Intermediate Language To C++) assuming that Intermediate Language is C# generic based software, Android and MS Phone and WHY the push to Native Plugins? The confusion comes with 2022.1 version and a complete NOT SO descriptive entailing procedures for using Native Plugins for OOP C++ Libraries.. It's hard at times to predict Unity's future and I am wondering if tutorials for this push in this direction whether Unity Learn and tutorials are forthcoming???

    IL2CPP Overview

    The IL2CPP (Intermediate Language To C++) scripting backend
    is an alternative to the Mono backend. IL2CPP provides better support for applications across a wider range of platforms. The IL2CPP backend converts MSIL (Microsoft Intermediate Language) code (for example, C# code in scripts) into C++ code, then uses the C++ code to create a native binary file (for example, .exe, .apk, or .xap) for your chosen platform.
     
    Last edited: Jan 10, 2022
  9. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Unfortunately there's no easy way to do it. C# only supports invoking functions (and not methods) that are annotated with the extern "C" designation. And in most cases, you have to manually specify which functions are exported.

    It's defined when compiling for Windows using Visual C++ or Clang compilers.


    IL2CPP is just a tool for us to run C# code in a cross platform way. Since every platform has a C++ compiler, IL2CPP makes porting Unity to new platforms much easier. It's still a fully featured .NET runtime with a garbage collection and virtual machine - it only uses C++ instead of a JIT. It mostly has no impact on native plugins as invoking functions in them uses the same mechanism. The only thing it makes easier is that it allows you to compile the C++ code into the same binary as your C# code so you avoid the performance penalty for crossing .dll boundaries. You can read about it here: https://docs.unity3d.com/Manual/macOSPlayerCPlusPlusSourceCodePluginsForIL2CPP.html
     
  10. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,571
    That was before Unity 5.

    The best idea is to use C# libraries, if available.

    Interfacing with C++ code from C# can be difficult, and you can't use things like C++ templates.
    You can, howver, easily interface with C-style APIs. You'll still need to write a lot of glue code.

    C++ does not have properties and interfacing with OOP C++ code from C# is not easy.
    https://stackoverflow.com/questions/315051/using-a-class-defined-in-a-c-dll-in-c-sharp-code

    So you'd need to design a set of function to interact with that large C++ library. T hat's why using C# library, when available, is a good idea - less hassle.
     
  11. UniteMage

    UniteMage

    Joined:
    Aug 22, 2012
    Posts:
    120
    Lost in Unity Space... OK

    Unless I can find a sophisticated AI code converter FROM Template C++ to Generic C#, then I have to learn ADVANCED Csharp idiosyncrasies....

    Thanks I Love Challenges.

    Many in the industry would narrow the modern Programming languages down by encapsulating it into a singularity called abstraction.

     
    Last edited: Jan 11, 2022
  12. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,571
    I'm not sure if it is advanced or not, but it is not beginner. Interfacing with C++ requires some familiarity with C++. You'll also need to design functions used by C# in a specific way. As you cannot call C++ class directly from C#. You also need solid understanding of t he way things are laid out in memory.

    Passing something like a struct to C++ side would require you to write a C# equivalent of the same struct, possibly with extra attributes that define memory layout of it in memory. This is what I call "writing glue code" and it is very tedious.

    The related reading kinda starts here:
    https://docs.microsoft.com/en-us/dotnet/standard/native-interop/type-marshaling

    There's also a VERY annoying gotcha that C# Marshalling/Interop API was designed for interfacing with Win32 API calls, and as a result C# bool turns into a 32-bit DWORD by default, while C++ wants bool to be one byte.
     
  13. UniteMage

    UniteMage

    Joined:
    Aug 22, 2012
    Posts:
    120
    What I meant by Lost in Unity Space is the obvious. Of course many in their own dogmatic world is about control. The goal is the quick hand performing the illusive tricks that Unity has to offer.... Come on, as Serena Williams yells out, get with the GAME.
     
  14. Neonlyte

    Neonlyte

    Joined:
    Oct 17, 2013
    Posts:
    516
    What @Tautvydas-Zilys meant was that you have to make C-style wrapper functions that calls the C++ methods, and then in a C# class, you make an extern method that mirrors the C functions. Here is an example:

    C++:
    Code (cpp):
    1. extern "C" void* class_A_new()
    2. {
    3.     return new A();
    4. }
    5.  
    6. extern "C" void class_A_dealloc(void* handle)
    7. {
    8.     delete handle;
    9. }
    10.  
    11. extern "C" void class_A_foo(void* handle)
    12. {
    13.     A* instance = static_cast<A*>(handle);
    14.     instance->foo();
    15. }
    16.  
    17. class A
    18. {
    19. public:
    20.     void foo()
    21.     {
    22.           // Do stuff.
    23.     }
    24. }
    C#:
    Code (CSharp):
    1. using System;
    2. using System.Runtime.InteropServices;
    3.  
    4. class A
    5. {
    6.     private IntPtr nativeHandle;
    7.  
    8.     public A()
    9.     {
    10.         nativeHandle = class_A_new();
    11.     }
    12.  
    13.     ~A()
    14.     {
    15.         class_A_delete(nativeHandle);
    16.     }
    17.  
    18.     public void Foo()
    19.     {
    20.         class_A_foo(nativeHandle);
    21.     }
    22.  
    23.     [DllImport("YOUR LIBRARY NAME HERE")]
    24.     private static extern IntPtr class_A_new();
    25.  
    26.     [DllImport("YOUR LIBRARY NAME HERE")]
    27.     private static extern void class_A_delete(IntPtr handle);
    28.  
    29.     [DllImport("YOUR LIBRARY NAME HERE")]
    30.     private static extern void class_A_foo(IntPtr handle);
    31. }
    Now before anyone else say anything, I know that for native resources I should conform the C# class to IDisposable. I'm trying to go for the easiest example.
     
  15. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,571
    You completely lost me here.
     
    angrypenguin and Neonlyte like this.
  16. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,571
    Yes, that's the rough idea. Lots of glue code.

    First you write the class in C++, then you write a wrapper for it in C++, then you write its doppelganger in C#, and if the class uses struct, you write duplicates for those in C# as well, and ensure they marshal properly.

    It is a fairly tedious thing to do.
     
  17. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    If the library is C++, you can potentially use SWIG (http://www.swig.org/) to generate C# wrappers, but it is a bit of work to set up.
     
  18. DragonCoder

    DragonCoder

    Joined:
    Jul 3, 2015
    Posts:
    1,699
    When I had a similar problem at developing a C++ dll I sort of emulated the association of instances by using an ID on unity side and list (vector) of instances on the C++ list.
    Whenever a new instance was needed, the C++ method created it, added a reference to it, to the vector and then returned its index in that vector to Unity.

    Then every further call that would affect a specific instance has the instance id as its first parameter.
    The C++ side just looks up the right field in the vector to get the reference to the required instance to affect.

    Not a system suited for a high frequency of instance creation and destruction, but it's fairly solid and without a very high performance impact.

    That you need a form of wrapper is annoying but that's unfortunately almost always the case when combining completely different programming languages. Therefore ideally when designing DLLs for Unity, try to make the DLL part as autonomous as possible. Have few calls from Unity and not interact with it all the time.
     
    Last edited: Jan 14, 2022
    angrypenguin likes this.