Search Unity

[Solved] XAMLUnityConnection in IL2CPP : Xaml C# <-> IL2CPP

Discussion in 'Windows' started by Cripple, Sep 14, 2017.

  1. Cripple

    Cripple

    Joined:
    Aug 16, 2012
    Posts:
    88
    Hi,

    I can't find any documetation about how to create communication Unity <-> XAML when scripting backend is il2CPP.

    My XAML host is also in C#.

    Any idea about how to achieve the communication please ?
     
  2. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    7,036
    You'll have to create a C++ interface with the communication functionality you need, implement it in C# on either IL2CPP side or VS side, then pass it to the other side through C++ and finally call methods on it.

    I assume you have Unity side and the XAML side working in the same process except the communication part?
     
  3. Cripple

    Cripple

    Joined:
    Aug 16, 2012
    Posts:
    88
    Yes we already have an il2cpp export of a project that is hosted in XAML using C#.
    We can't find a way of doing the communication IN and OUT.

    Could you provide an example of it please ?
     
  4. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    7,036
    Sure.

    Make a windows runtime component with this code:

    Code (csharp):
    1. namespace IL2CPPToDotNetBridge
    2. {
    3.    public interface class IDotNetBridge
    4.    {
    5.    public:
    6.        void MyFunction1();
    7.        void MyFunction2(Platform::String^ arg);
    8.    };
    9.  
    10.    public interface class IIL2CPPBridge
    11.    {
    12.    public:
    13.        void MyFunction3();
    14.        void MyFunction4(int arg);
    15.    };
    16.  
    17.    public ref class BridgeBootstrapper sealed
    18.    {
    19.    public:
    20.        static IDotNetBridge^ GetDotNetBridge()
    21.        {
    22.            return m_DotNetBridge;
    23.        }
    24.  
    25.        static void SetDotNetBridge(IDotNetBridge^ dotNetBridge)
    26.        {
    27.            m_DotNetBridge = dotNetBridge;
    28.        }
    29.  
    30.        static IIL2CPPBridge^ GetIL2CPPBridge()
    31.        {
    32.            return m_IL2CPPBridge;
    33.        }
    34.  
    35.        static void SetIL2CPPBridge(IIL2CPPBridge^ il2cppBridge)
    36.        {
    37.            m_IL2CPPBridge = il2cppBridge;
    38.        }
    39.  
    40.    private:
    41.        static IDotNetBridge^ m_DotNetBridge;
    42.        static IIL2CPPBridge^ m_IL2CPPBridge;
    43.  
    44.        BridgeBootstrapper();
    45.    };
    46.  
    47.    IDotNetBridge^ BridgeBootstrapper::m_DotNetBridge;
    48.    IIL2CPPBridge^ BridgeBootstrapper::m_IL2CPPBridge;
    49. }
    Compile it for all CPU architectures you care about, drop the DLLs into your Unity project, and also drop one .winmd file into your Unity project (doesn't matter which one - they will all be identical).

    Then in Unity, do this:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. #if ENABLE_WINMD_SUPPORT
    5.  
    6. using IL2CPPToDotNetBridge;
    7.  
    8. class IL2CPPBridge : IIL2CPPBridge
    9. {
    10.     public void MyFunction3()
    11.     {
    12.         Debug.Log("Inside MyFunction3");
    13.     }
    14.  
    15.     public void MyFunction4(int arg)
    16.     {
    17.         Debug.Log("Inside MyFunction4: " + arg);
    18.     }
    19. }
    20.  
    21. #endif
    22.  
    23. public class Script : MonoBehaviour
    24. {
    25.     void Awake()
    26.     {
    27. #if ENABLE_WINMD_SUPPORT
    28.         BridgeBootstrapper.SetIL2CPPBridge(new IL2CPPBridge());
    29. #endif
    30.     }
    31.  
    32.     void Start()
    33.     {
    34. #if ENABLE_WINMD_SUPPORT
    35.         var dotnetBridge = BridgeBootstrapper.GetDotNetBridge();
    36.         dotnetBridge.MyFunction1();
    37.         dotnetBridge.MyFunction2("Hello from il2cpp");
    38. #endif
    39.     }
    40. }
    On VS side, do this on startup:

    Code (csharp):
    1. using IL2CPPToDotNetBridge;
    2.  
    3. class DotNetBridge : IDotNetBridge
    4. {
    5.     public void MyFunction1()
    6.     {
    7.         var il2cppBridge = BridgeBootstrapper.GetIL2CPPBridge();
    8.         il2cppBridge.MyFunction3();
    9.         il2cppBridge.MyFunction4(535);
    10.     }
    11.  
    12.     public void MyFunction2(string arg)
    13.     {
    14.         Debug.WriteLine("Inside MyFunction2: " + arg);
    15.     }
    16. }
    17.  
    18. static void Main(string[] args)
    19. {
    20.     BridgeBootstrapper.SetDotNetBridge(new DotNetBridge());
    21.  
    22.     ....
    23. }
    And you're done! You should get this output upon success:

    Code (csharp):
    1.  
    2. Inside MyFunction3
    3. UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object)
    4. UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
    5. UnityEngine.Logger:Log(LogType, Object)
    6. UnityEngine.Debug:Log(Object)
    7. IL2CPPBridge:MyFunction3()
    8. IL2CPPToDotNetBridge.IDotNetBridge:MyFunction1()
    9. Script:Start()
    10. (Filename: C:\buildslave\unity\build\artifacts/generated/Metro_IL2CPP/runtime/DebugBindings.gen.cpp Line: 51)
    11.  
    12. Inside MyFunction4: 535
    13. UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object)
    14. UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
    15. UnityEngine.Logger:Log(LogType, Object)
    16. UnityEngine.Debug:Log(Object)
    17. IL2CPPBridge:MyFunction4(Int32)
    18. IL2CPPToDotNetBridge.IDotNetBridge:MyFunction1()
    19. Script:Start()
    20. (Filename: C:\buildslave\unity\build\artifacts/generated/Metro_IL2CPP/runtime/DebugBindings.gen.cpp Line: 51)
    21.  
    22. Inside MyFunction2: Hello from il2cpp
     
  5. Cripple

    Cripple

    Joined:
    Aug 16, 2012
    Posts:
    88
    Thank you,

    It looks good, I am going to test this :)
     
  6. Cripple

    Cripple

    Joined:
    Aug 16, 2012
    Posts:
    88
    Hi,

    I have implemented the solution and everything is fine. Thanks for the tip :)
     
  7. malindaw

    malindaw

    Joined:
    Mar 5, 2019
    Posts:
    8
    Hi,T@Tautvydas-Zilys.

    I have done a project in UWP with .NET scripting backend. So now I need to do it using IL2CPP scripting backend. So without changing that, for testing I created a new unity uwp project using IL2CPP backend and another UWP C# visual studio project. So if there is way to communicate between those two projects (show unity screen in a part of my XAML view and display something on it by addressing unity functions from MainPageXaml.cs), I can develop the rest of my project using IL2CPP backend scripting. So can you please state the steps of doing this one?
     
    Last edited: Apr 10, 2019
  8. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    7,036
    Did the steps I posted above not work for you for communication?
     
  9. malindaw

    malindaw

    Joined:
    Mar 5, 2019
    Posts:
    8
    Thank you for your quick response. I think your code can do the thing I want. But I want to clarify few things. These are the tasks I have done so far.

    1) Created a unity project and built it with IL2CPP backend scripting for UWP.
    2) Then created UWP c# project in Visual studio and copied the generated files into the above project's UWP part.
    3) Then created the cpp interface with the given code on a windows run-time component.
    4) And run it and copied the generated dll files and .winmd file into my unity project. (into "Assets/Scripts/" folder ).
    5) Then added the unity code in Script.cs file in unity Scripts folder.
    6) Then created c# code in VS and added the given code there.

    As well as there was an error:

    " Program has more than one entry point defined. Compile with /main to specify the type that contains the entry point. UWPCpp F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\MainPage.xaml.cs 35 Active
    "'

    So I added this part " BridgeBootstrapper.SetDotNetBridge(new DotNetBridge());" in MainPage block and run it.

    My code:

    Code (CSharp):
    1. namespace UWPCpp
    2. {
    3.     /// <summary>
    4.     /// An empty page that can be used on its own or navigated to within a Frame.
    5.     /// </summary>
    6.     public sealed partial class MainPage : Page
    7.     {
    8.  
    9.         public MainPage()
    10.         {
    11.             this.InitializeComponent();
    12.             BridgeBootstrapper.SetDotNetBridge(new DotNetBridge());
    13.             // BridgeBootstrapper.SetDotNetBridge(new DotNetBridge());
    14.  
    15.         }
    16.  
    17.  
    18.  
    19.         class DotNetBridge : IDotNetBridge
    20.         {
    21.             public void MyFunction1()
    22.             {
    23.                 Debug.WriteLine("I'm FUnction1");
    24.                 var il2cppBridge = BridgeBootstrapper.GetIL2CPPBridge();
    25.                 il2cppBridge.MyFunction3();
    26.                 il2cppBridge.MyFunction4(535);
    27.             }
    28.  
    29.             public void MyFunction2(string arg)
    30.             {
    31.                 Debug.WriteLine("I'm FUnction2");
    32.                 Debug.WriteLine("Inside MyFunction2: " + arg);
    33.             }
    34.  
    35.         }
    36.     }
    37.  
    38. }
    But I got a result as below. Couldn't get that debug statments.

    Result:

    "
    Code (CSharp):
    1. 'UWPCpp.exe' (CoreCLR: DefaultDomain): Loaded 'C:\Program Files\WindowsApps\Microsoft.NET.CoreRuntime.1.1_1.1.27004.0_x64__8wekyb3d8bbwe\System.Private.CoreLib.ni.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    2. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\entrypoint\UWPCpp.exe'. Symbols loaded.
    3. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\System.Runtime.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    4. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'C:\Program Files\WindowsApps\Microsoft.NET.CoreRuntime.1.1_1.1.27004.0_x64__8wekyb3d8bbwe\mscorlib.ni.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    5. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\WinMetadata\Windows.winmd'. Module was built without symbols.
    6. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\System.Runtime.InteropServices.WindowsRuntime.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    7. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\System.Runtime.WindowsRuntime.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    8. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\System.Numerics.Vectors.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    9. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\System.Runtime.WindowsRuntime.UI.Xaml.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    10. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\Microsoft.UI.Xaml.Markup.winmd'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    11. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\System.Threading.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    12. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\System.Collections.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    13. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\System.Reflection.dll'. Module was built without symbols.
    14. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\System.Threading.Tasks.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    15. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\System.Reflection.Extensions.dll'. Module was built without symbols.
    16. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\System.Linq.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    17. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\IL2CPPToDotNetBridge.winmd'. Module was built without symbols.
    18. 'UWPCpp.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'F:\Malinda\UWP_Projects\Test\NewProject\UWPCpp\bin\UWPCpp\bin\x64\Debug\AppX\System.Private.Uri.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
    19. The thread 0x2f94 has exited with code 0 (0x0).
    20. The thread 0x104c has exited with code 0 (0x0).
    "
     
    Last edited: Apr 11, 2019
  10. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    7,036
    Try switching to "Mixed Mode" debugging in Visual Studio Project Properties, Debugging tab.

    By the way, does Unity get initialized properly?
     
  11. madhur

    madhur

    Joined:
    May 16, 2012
    Posts:
    86
    @Tautvydas-Zilys I am trying to integrate an UWP C# app with a UWP app built from Unity IL2CPP (as .net is deprecated)

    In the below question do you mean that integration part? Before following your steps to get the communication part working, I think first I need to put my C# uwp project and the Unity IL2CPP built C++ uwp project in to one project.

    It will be really helpful if you can provide the exact steps I have to follow to do that or any reference to such guide.

    My requirement is I have a C# UWP project coded in VS. Now I need to open 3D models inside that app, so need to include Unity inside my UWP project.

    Thank you.

     
  12. malindaw

    malindaw

    Joined:
    Mar 5, 2019
    Posts:
    8
    OK I'll try it. I have spent about three days to solve this issue. So I really appreciate your contribution. I wanted to clarify whether the above procedure is correct or wrong. What you have meant by Unity initialization?
    I have created the UWP project with IL2CPP scripting backend, and now I have created another C# UWP project just using visual studio(not by Unity). Then I copied those files also into the project folder of the first project. Then I followed your procedure. But I think the reason for getting a null instance of that bridge is lack of any connection between unity and C# UWP project. I think they: [UWP C# prject and UWP CPP Unity project] work as seperate projects. Finally my target is to load a unity scene on a section of my C# UWP app.
     
  13. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    7,036
  14. malindaw

    malindaw

    Joined:
    Mar 5, 2019
    Posts:
    8
    Thanks for your quick response. Yes, I think that the reason for this issue, when I run the project built from unity with IL2CPP backend scripting, I can see the unity scene in my UWP app. But it can not be seen in my C# project. Because it's just a UWP project built from VS.
     
  15. malindaw

    malindaw

    Joined:
    Mar 5, 2019
    Posts:
    8
    Can you tell me the steps of creating a project like this "https://github.com/TautvydasZilys/unity-uwp-il2cpp-with-csharp-project-example"

    Another thing is I used this example project and included the codes you provided there and tested the output result. But again I got the same output, (Null Reference Exception) when using the below statement to call unity methods directly.
    Code (CSharp):
    1.             Debug.WriteLine("This is just for testing!");
    2.             bg.MyFunction1( );
     
    Last edited: Apr 12, 2019
  16. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    7,036
  17. malindaw

    malindaw

    Joined:
    Mar 5, 2019
    Posts:
    8
    When I call a method in Unity script,
    Code (CSharp):
    1.             BridgeBootstrapper.SetDotNetBridge(bg = new DotNetBridge());
    2.             Debug.WriteLine("This is just for testing!");
    3.             bg.MyFunction2("Malinda");
    4.            bg.MyFunction1();
    Why do I receive a Null Pointer Exception? I think if I can find a solution for that one, the whole problem can be solved.
     
  18. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    7,036
    Which line causes it? And how is BridgeBootstrapper defined?
     
  19. malindaw

    malindaw

    Joined:
    Mar 5, 2019
    Posts:
    8
    I just use that Debug statements to check whether DotNetBridge() is NULL or not. Your code snippets are used in the rest of the code. Problem is occurred in line NUmber 4.
     
  20. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    7,036
    Perhaps the exception is thrown from inside that function?
     
  21. malindaw

    malindaw

    Joined:
    Mar 5, 2019
    Posts:
    8
    Yes, I think so.... Still I couldn't achieve my goal. Couldn't find the exact issue in doing that one. I'm expecting a clear procedure to do it. In .NET I could do it easily but here when using IL2CPP its really not easy like that one. So can you consider about this matter.
     
  22. madhur

    madhur

    Joined:
    May 16, 2012
    Posts:
    86
    @malindaw In the last post of this thread I have given the steps I used to create such project.
    https://forum.unity.com/threads/build-for-uwp-c-with-il2cpp.663130/#post-4472917
     
  23. MuhammadHaseeb56

    MuhammadHaseeb56

    Joined:
    Mar 12, 2019
    Posts:
    8
    i try so many time but i didnt find any solution i make unity uwp build il2cpp now i want to add "ads" in my project i don't know how to call the function in mainpage.xaml.cpp and communicate with unity eventhandler before that i was using .net scripting backend i used this code to calling the ads calling or other functions
    WP_Events_Controller.likeUs += WP_Events_Controller_likeUs;
    there WP_Events_Controller.likeUs is a unity delegate where likeUs function defined

    async private void WP_Events_Controller_likeUs(object sender, EventArgs e)
    {
    //await Windows.System.Launcher.LaunchUriAsync(new Uri(@"www.example.com"));
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
    {

    and this the function i wrote in mainpage.xaml.cs

    now i dont know how to do this in il2cpp scripting backend .. kindly please help me to solve this problem.. Thank you
     
    Last edited: Feb 6, 2020
  24. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    7,036
    You cannot call into your C# code from MainPage.xaml.cpp like you could with .NET scripting backend. I suggest putting all this code inside your scripts in your Unity Project instead.
     
  25. MuhammadHaseeb56

    MuhammadHaseeb56

    Joined:
    Mar 12, 2019
    Posts:
    8
    but windows advertisement SDk reference add in the visual studio how i can call the ads in unity ?
     
  26. MuhammadHaseeb56

    MuhammadHaseeb56

    Joined:
    Mar 12, 2019
    Posts:
    8
    kindly please help me how i can implement ads in uwp il2cpp build
     
  27. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    7,036
    Add the SDK to your Unity project instead of referencing it from generated Visual Studio project.
     
  28. MuhammadHaseeb56

    MuhammadHaseeb56

    Joined:
    Mar 12, 2019
    Posts:
    8
    Thank you so much but please guide me the procedure how i can call the ads for uwp project with il2cpp build?
     
  29. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    7,036
    Please stop spamming the forums in different threads. That will not help you to solve your issue faster.

    Now, with that out of the way, can you clarify which step isn't clear? You said you reference the ads SDK from your visual studio project. Instead, you need to find where the ads SDK is installed on disk (by looking at references properties in solution explorer), and then copy .winmd/.dll files from that SDK into Unity project. Once you do that, you need to configure those files in the plugin inspector to be compatible with UWP, and finally just call into the SDK directly from your C# scripts.
     
unityunity