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

Communicating C# with C++

Discussion in 'Scripting' started by Dam-Pete, May 19, 2011.

  1. Dam-Pete

    Dam-Pete

    Joined:
    Jun 11, 2010
    Posts:
    54
    This isn't exactly a Unity-specific question, but since I'm implementing this in Unity some people might have tried doing this.

    I have a C++ plugin which has "observables". I would like to register a callback from a C# function (from Unity) to my C++ observable class. Is it possible for my C++ code to call a C# callback? Any ideas how this could be done?

    I know very little of C# and basically I found something related to "delegates", but I don't know how to use it and have no idea how it would integrate with C++.

    Thanks in advance
     
    AntonioModer and aparajithsairam like this.
  2. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    It is technically possible but your C++ plugin must run in the engines thread, otherwise it will crash if the callback you try to call accesses anything from the unity engine. Unity is not thread safe and you must not access its "space" from another thread.

    To create such a callback, just send the function out to the C++ layer for calling through marshaling, thats rather straight forward, for void return type no effort is required at all.
     
  3. ZeroStride

    ZeroStride

    Joined:
    Mar 9, 2011
    Posts:
    34
  4. Dam-Pete

    Dam-Pete

    Joined:
    Jun 11, 2010
    Posts:
    54
    Thanks a lot for the help guys...

    Now I have another question

    How would I define that using Unity C# DLLImport?

    Obviously doesn't work. I tried changing the function pointer (in the DLL and in C# script) from ANSWERCB to System::IntPtr, but I wasn't able to compile the DLL this way (I even tried compiling with /clr, which I think makes the DLL stop working in Unity, but even with /clr it failed to compile).

    Not sure how I can get this specific part to work now... any ideas?


    Tried changing ANSWERCB to void*, but I don't know how that would look like in C# either... Sorry, I really don't know how to work with C# :(
     
    Last edited: May 24, 2011
    dan_ginovker likes this.
  5. ZeroStride

    ZeroStride

    Joined:
    Mar 9, 2011
    Posts:
    34
  6. Dam-Pete

    Dam-Pete

    Joined:
    Jun 11, 2010
    Posts:
    54
    I was able to get it to work, thanks a lot guys.

    In case anyone has the same doubt and is looking for an answer, here's an example:


    C++ DLL code (build as DLL, disable /clr [Common Language Runtime])

    Unity C# Script using the DLL
     
    Last edited: May 25, 2011
  7. ankur6ue

    ankur6ue

    Joined:
    Aug 4, 2011
    Posts:
    4
    Thanks for posting the code! Very helpful!
     
  8. Deleted User

    Deleted User

    Guest

    Two years later and I found it very helpful as well.

    Thanks!
     
  9. schpidah

    schpidah

    Joined:
    Jan 15, 2014
    Posts:
    1
    In the example script, can myCallback() be static? Thanks for the example code, it is very helpful.
     
  10. stealdream

    stealdream

    Joined:
    Jan 25, 2014
    Posts:
    1
    So greate!!! I spent 2 days in this problem.
     
  11. natbro206

    natbro206

    Joined:
    Mar 15, 2014
    Posts:
    2
    thank you - it's insane that this was so difficult to track down.

    for those of you that may run across this in the future in the context of Unity 3D, here is an example native-code plugin and test Unity project which demonstrate callbacks, recurring callbacks, and simple byte marshaling from native code back to Unity/C#. It's pretty applicable to any kind of mono/C# integration, though.
     
    Last edited: Oct 15, 2014
    cmberryau and DarkSchneider like this.
  12. St0fF

    St0fF

    Joined:
    Feb 4, 2015
    Posts:
    1
    I've tried this on Windows, having in mind that my dll calls unity from another thread. It works well as long as you're only trying to update some data members of the C# class (like in my example: 2 ints). But if you're trying to do something with the updated ints like reposition some object, it won't work anymore and unity crashes. So it all works as espected.

    The real deal would be: how do I call such a callback function from my dll inside the thread that registered the callback? Any ideas?
     
  13. Snipe3000

    Snipe3000

    Joined:
    Aug 31, 2013
    Posts:
    8
    Hi guys, sorry to revive an old thread. I'm desperately trying to understand Delegates and Marshaling in order to be able to call a Unity function from a plugin. From what I can tell, Dam-Pete's solution does the opposite; It looks like Unity is calling a function from the plugin.
    Does anyone know how to get a plugin to call a C# unity function?

    Thanks
     
  14. Aithoneku

    Aithoneku

    Joined:
    Dec 16, 2013
    Posts:
    67
    Many years later and this helped me a lot!

    Probably late, but for people in future: actually, Pete's solution (post #6) works exactly like that. Or to be more precise: function TakesCallback is called from Unity to C/C++ plugin. But with this function you register a C# callback/delegate so in future, when you need to communicate from plugin to C#, you can use this delegate.
     
  15. Aithoneku

    Aithoneku

    Joined:
    Dec 16, 2013
    Posts:
    67
    If would like to clarify one thing for people searching this problem in future: generally, when you call something on C/C++ side from C#, anything you pass will exist (is valid) only during the call, which would be pretty problematic for delegates. However delegates are an exception: function pointer passed to C/C++ from C# is valid as long as original C# delegate object exists. That means we should create a delegate variable for the C/C++ callback and keep it alive while C/C++ can invoke it! (Of course it's not necessary if the callback can be invoked only during the C/C++ call.) Source: http://www.mono-project.com/docs/advanced/pinvoke/#memory-boundaries
     
  16. unity_r71wO1KFVJaK9w

    unity_r71wO1KFVJaK9w

    Joined:
    Dec 15, 2020
    Posts:
    7
    Hi, Thanks for the code but some native libraries are using c structs containing multiple callbacks. How to use those in unity C#.
    ##real vnc sdk code
    typedef struct {
    void(*requestUserCredentials)(void* userData,
    vnc_Viewer* viewer,
    vnc_bool_t needUser,
    vnc_bool_t needPasswd);

    void
    (*cancelUserCredentialsRequest)(void* userData,
    vnc_Viewer* viewer);
    } vnc_Viewer_AuthenticationCallback;

    Here we have to register for callback in c
    //For documentation visit https://www.realvnc.com/de/developer/docs/latest/api/c/
    vnc_Viewer_setAuthenticationCallback(vnc_Viewer *viewer, const vnc_Viewer_AuthenticationCallback *callback, void *userData)

    Sets the callback to be called when a username and/or password is required.