Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Using native C++ implemented with wrappers throws exception

Discussion in 'Scripting' started by MrDyrektor, Oct 22, 2017.

  1. MrDyrektor

    MrDyrektor

    Joined:
    Nov 13, 2016
    Posts:
    14
    Hello!

    I'm using some native C++ code to speed up some calculations. I'd been implementing it directly to Unity project with [DllImport] attribute. However, passing data with marshalling gave me big performance drop, so I decided to wrap this native DLL with C++/CLI.

    Troubles start here. As you know, Unity doesn't detect managed C++ libraries as managed, but as native. I implemented my wrapper to main project and used some functions from it. Visual Studio didn't give me any errors, but Unity's compiler did. I've realised that this is caused by detecting my wrapper as native, so I created new .dll in C# where I implemented my C++/CLI .dll. Unity compiles now, but there is another issue which I can't resolve.

    Always when I try to call method from my libraries, C# .dll call is fine, C++/CLI call is fine too, but call to native C++ from C++/CLI throws NotImplementedException. I tried various solutions, adding __declspec to structures and classes in native code, implementing it to projects as full project or just compiled .dll, but I didn't find a solution. I created .exe in C++/CLI and C# where I called same methods, and both didn't throwed any exceptions.

    Does anyone know what is going on here?

    This issue is the same problem LINK
     
  2. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Are you sure it's coming from that code?
    What calculation have you moved to C++? Is it even worth it? The post you linked is about handtracking.

    I'm not well informed about the C++/CLI part in combination with Unity. I've only ever called into C++ libs from C#.

    Anyway, if that already causes a big performance impact, it might not be worth doing the calculation in C++ anyway.
     
  3. MrDyrektor

    MrDyrektor

    Joined:
    Nov 13, 2016
    Posts:
    14
    Oh cmon, I expected questions of type "is it worth"? - the answer is YES.

    I'm sure that it comes from connection between native and managed C++, because when I put Debug::Log before any call from native, it logs ;)
     
  4. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Well, that isn't quite obvious as it seems. There is a significant overhead for calling into unmanaged code - relatively to calling C# methods - but when you say it's really worth it, you're either using some extremely well-optimized instructions that naturally out-perform similar C# code or it's really an expensive calculation.

    If it was the latter, the actual call into the unmanaged plugin should be negligible - however, according to your post it's not.
    That's why I'm curious about the kind of calculation we're talking about - if you don't mind.

    Spontaneuosly, I'd categorize the available options like:

    1) not significantly faster, so just use an optimized C# version
    2) slightly faster but the performance benefit is killed by calling into the unmanaged code, so you end up at 1)
    3) much faster due to special instructions/special optimization or simply due to the use of pointers*, still being killed by calling into native code.
    4) much faster using native code so that the call into native code is negligible

    Not sure if you've actually compared the calculations in both languages with a reasonable and fair test. Keep in mind applications, especially a huge ones like Unity, always need time to spin up and do various other things that may influence a test. If you tested this in the editor, try the build.

    * If you come to the conclusion that it's 3) and it's purely due to the use of pointers, you may try unsafe code as well.

    Other than that, are there any reasons you can't use threading?

    It's a given fact there are limitations and performance impacts when you want to call into that code, and you cannot really change that.
    As for "managed C++", like stated earlier, I can't speak much from experience. I've tried to get this to work for a project in the office some time ago and it's a real pain to get it working in Unity. As mentioned, I've never made it work - thus it's never been a considerable option - and thus I'm not sure if it saves a lot of performance after all.
     
    Last edited: Oct 22, 2017
    MrDyrektor likes this.
  5. MrDyrektor

    MrDyrektor

    Joined:
    Nov 13, 2016
    Posts:
    14
    I got what you mean. Calculations which I make in C++ are not only just significantly faster in computations, but also are doing a lot of stuff on memory - converting splatmaps, heightmaps, packing it, etc.- my project requiers doing these computations in a very short time - these computations in C# took over 60ms for one terrain piece (mostly due to GC, after optimization 35ms), and after conversion to C++ they take ~5ms (!) for each. I think that call time is totally negligible there :D

    Maybe I'll just use P/Invoke and marshalling as I'm doing it now (I've abandoned writing in C++/CLI, since I couldn't force it to work :p), until Unity Technologies will do something with it.
     
    Last edited: Oct 22, 2017
    Suddoha likes this.
  6. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Well, if it takes 5ms (in C++) for the computation itself, you probably shouldn't bother about the call at all. :D
     
  7. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Whats going on is that your codes and lib are being washed by the Unity wrapper compiler. Every thing you wrote in C# or c++ will end up different than what you coded. I would stick to C# if i where you, there is no gain to go c++ route since its all c++ in the end. If you build your own program in c++ that is another thing thought.