Search Unity

IL2CPP Callbacks In UWP

Discussion in 'Windows' started by ClaytonOne, Jul 14, 2018.

  1. ClaytonOne

    ClaytonOne

    Joined:
    Sep 5, 2015
    Posts:
    89
    Hi, when using the .Net scripting backend its possible to pass a reference back from the UWP side to the Unity Side. For example we pass a reference to the SwapChainPanel like so from MainPage.xaml.cs

    CI.WSANative.Device.WSANativeProgressControl.Configure(GetSwapChainPanel());

    With the depreciation of the .Net scripting backend looming we are looking for a way to do this in IL2CPP, but haven't been able to find a way.

    Does anyone have any ideas?

    Thanks
     
  2. RobJellinghaus

    RobJellinghaus

    Joined:
    Jul 10, 2017
    Posts:
    17
    This looks like a pretty serious feature gap in IL2CPP that hopefully will block fully deprecating the .NET runtime until there's a way to do this. Did you file a feedback item? I'll upvote it if you do.
     
  3. timke

    timke

    Joined:
    Nov 30, 2017
    Posts:
    408
    Hi Jackal,

    Could you please provide a little more context around your project?

    From your description it sounds like your doing this with the .NET back-end and trying to replicate in il2cpp:

    - Building a Windows 10 XAML app
    - Modifying C# code within the generated VS project
    - Passing Windows objects (e.g. SwapChainPanel) from modified C# code into APIs exposed by a plugin

    Is there a specific error or problem you're hitting or do you just need general help porting your modified C# code to C++?

    The example line of code you gave is not an actual Unity API but instead it appears to be from the Windows Store Native plugin. Are the issues specific to this plugin are you also having issues with Unity specific APIs?

    Here are some links to relevant docs and forum posts I found which may be helpful:

    https://docs.unity3d.com/Manual/windowsstore-plugins-il2cpp.html
    https://forum.unity.com/threads/solved-xamlunityconnection-in-il2cpp-xaml-c-il2cpp.495345/
    https://forum.unity.com/threads/uwp-get-swapchainpanel-grid-in-il2cpp-xaml-build.502176/
     
  4. ClaytonOne

    ClaytonOne

    Joined:
    Sep 5, 2015
    Posts:
    89
    Hi @timke, you're correct yes we are trying to replicate the .Net code we have into IL2CPP.

    I'm the developer of the Windows Store Native plugin and we have a scenario where we need to pass the SwapChainPanel from the generated vs project into our plugin code on the Unity side.

    With the .Net scripting backend this is very simple as you can call your Unity code from the generated solution. I can't find a way to do this in IL2CPP as the code has obviously been converted to C++.

    Example as we have in .Net at the moment:

    Unity side we have a function

    Code (CSharp):
    1. public void SetSwapChain(SwapChainPanel swapChainPanel)
    2. {
    3.     // Do something with swapChainPanel
    4. }
    From the generated solution we can call the above function from MainPage.xml.cs

    Code (CSharp):
    1. SetSwapChain(GetSwapChainPanel());
    One of those links you posted may have the answer.
     
    Last edited: Jul 17, 2018
  5. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    This is doable. While you can’t talk from generated VS project directly to your IL2CPPed C# code, you can talk to C++ from both sides.

    Add two functions to a .cpp file: GetSwapChain and SetSwapChain (returning and taking IInspectable pointer), which retrieve and store it in a static variable. Put that C++ file into your Unity project, and from generated C++ code set the swap chain, and then retrieve it from your C# code.
     
  6. ClaytonOne

    ClaytonOne

    Joined:
    Sep 5, 2015
    Posts:
    89
    From the generated code how do I cast the

    "Windows::UI::Xaml::Controls::SwapChainPanel ^" to "IInspectable *"

    and on the Unity side how do I reference IInspectable? I saw in another example something like the below but for me UnmanagedType doesn't have the IInspectable value.

    [MarshalAs(UnmanagedType.IInspectable)]
     
    Last edited: Aug 12, 2018
  7. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Apologies for lack of code sample in my last message, I was on vacation and on my phone.

    On the managed side you should just be able to do this:

    Code (csharp):
    1. #if UNITY_WSA
    2. [DllImport("__Internal")]
    3. static extern SwapChainPanel GetSwapChainPanel();
    4. #endif
    And then in .cpp file that you drop in your project:

    Code (csharp):
    1. #include <wrl.h>
    2.  
    3. Microsoft::WRL::ComPtr<IInspectable> s_SwapChainPanelInspectable;
    4.  
    5. extern "C" IInspectable* GetSwapChainPanel()
    6. {
    7.     auto result = s_SwapChainPanelInspectable.Get();
    8.     result->AddRef();
    9.     return result;
    10. }
    11.  
    12. __declspec(dllexport) extern "C" void SetSwapChainPanel(IInspectable* swapChainPanel)
    13. {
    14.     s_SwapChainPanelInspectable = swapChainPanel;
    15. }
    And finally, in generated VS project code:

    Code (csharp):
    1. __declspec(dllimport) extern "C" void SetSwapChainPanel(IInspectable* swapChainPanel);
    2.  
    3. void SetSwapChainPanelWrapper(Windows::UI::Xaml::Controls::SwapChainPanel^ swapChainPanel)
    4. {
    5.     SetSwapChainPanel(reinterpret_cast<IInspectable*>(swapChainPanel));
    6. }
     
  8. ClaytonOne

    ClaytonOne

    Joined:
    Sep 5, 2015
    Posts:
    89
    Thanks look like its working.

    Slightly off topic but when compiling against IL2CPP for Window Universal 10 should I be able to use System.Net.Http.HttpClient? The build fails every time even when the code is inside

    #if (ENABLE_IL2CPP && UNITY_WSA_10_0)
    #endif

    Api Compat Level is 4.0

    tried scripting runtime version at 3.5 and 4.x but neither work (Unity 2018.2)
     
  9. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    How does the build fail? What does it say?
     
  10. ClaytonOne

    ClaytonOne

    Joined:
    Sep 5, 2015
    Posts:
    89
    @Tautvydas-Zilys It complains about HttpClient and anything else in the System.Net.Http namespace not exisiting.

    Works fine in the .Net build though
     
    Last edited: Aug 15, 2018
  11. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Could you try targeting .NET Standard 2.0 profile and see if it solves it? It could be that it's not referenced by default with 4.x (using .NET Standard 2.0 profile as an advantage of being more suited for IL2CPP so your builds will be quicker too).
     
  12. ClaytonOne

    ClaytonOne

    Joined:
    Sep 5, 2015
    Posts:
    89
    @Tautvydas-Zilys Interestingly that builds ok. Edit - it builds but seems to throw an invalid pointer exception in the native code when running, appears to be in the socket implementation.

    Since this is part of a plugin though I'm looking for more backwards compatibility.

    Surely an api compat level of .Net 4.x should be enough since HttpClient was added with .Net 4? The unity docs even state that it gives you access to the full .net 4 framework.

    On the above solution for the SwapChainPanel I get the error "Unable to marshal type Windows.UI.Xaml.Controls.SwapChainPanel" when I call GetSwapChainPanel()

    Thanks for your help so far :)
     
    Last edited: Aug 15, 2018
  13. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Yeah, do you have access to full .NET 4.x, but all of it is not referenced by default. You need to add a reference to System.Net.Http.dll. To do that, create "csc.rsp" file in the Assets folder in your project, and add "/r:System.Net.Http.dll" to it. Then, go to "E:\Builds\Unity 2018.1.7f1\Editor\Data\MonoBleedingEdge\lib\mono\4.5" and copy System.Net.Http.dll to your project root, next to your Assets and ProjectSettings folders (not inside of it). I know this is a bit clunky, but it's the best solution I can offer for now. Note: you'll have to update this DLL every time you update your Unity version.

    As for the Unable to marshal issue, you're right, our P/Invoke layer (foolishly) doesn't support that.

    There is another solution, though. Instead of putting that C++ code inside Unity project, put it in new DLL (In Visual Studio, do File -> New Project, Visual C++ -> Windows Universal -> Windows Runtime Component). And instead of exposing it as raw C++ API, expose it as part of Windows Runtime class as a static variable. Then put the compiled .winmd and .dll file into your project (you'll need one per CPU architecture you plan to ship on), build it, and then in exported VS project add a reference to the winmd file of your plugin.

    Here's example code of the mentioned DLL (no longer have to play with IInspectable, casting or P/Invoke signatures, just call these functions directly):

    Code (csharp):
    1. #pragma once
    2.  
    3. namespace WindowsRuntimeComponent3
    4. {
    5.     public ref class Class1 sealed
    6.     {
    7.     public:
    8.         static Windows::UI::Xaml::Controls::SwapChainPanel^ GetSwapChainPanel();
    9.         static void SetSwapChainPanel(Windows::UI::Xaml::Controls::SwapChainPanel^ panel);
    10.  
    11.     private:
    12.         Class1();
    13.  
    14.         static Windows::UI::Xaml::Controls::SwapChainPanel^ s_Panel;
    15.     };
    16.  
    17.     Windows::UI::Xaml::Controls::SwapChainPanel^ Class1::s_Panel;
    18.  
    19.     Windows::UI::Xaml::Controls::SwapChainPanel^ Class1::GetSwapChainPanel()
    20.     {
    21.         return s_Panel;
    22.     }
    23.  
    24.     void Class1::SetSwapChainPanel(Windows::UI::Xaml::Controls::SwapChainPanel^ panel)
    25.     {
    26.         s_Panel = panel;
    27.     }
    28. }
     
  14. ClaytonOne

    ClaytonOne

    Joined:
    Sep 5, 2015
    Posts:
    89
    @Tautvydas-Zilys Ok so I've built the winmd + dll and added them to the Unity project.

    Set the following properties on them

    - Include Platforms - WSAPlayer
    - SDK - UWP
    - Scripting Backend - IL2CPP

    - DLL set to x86

    But visual studio fails to resolve the class / namespace so I can't call HelloWorld.WSACommonBridge.GetSwapChainPanel() from the Unity side. Any ideas?

    Code
    Code (CSharp):
    1. #pragma once
    2.  
    3. namespace HelloWorld
    4. {
    5.     public ref class WSACommonBridge sealed
    6.     {
    7.     public:
    8.         static Windows::UI::Xaml::Controls::SwapChainPanel^ GetSwapChainPanel();
    9.         static void SetSwapChainPanel(Windows::UI::Xaml::Controls::SwapChainPanel^ panel);
    10.     private:
    11.         WSACommonBridge();
    12.         static Windows::UI::Xaml::Controls::SwapChainPanel^ _swapChainPanel;
    13.     };
    14.  
    15.     Windows::UI::Xaml::Controls::SwapChainPanel^ WSACommonBridge::_swapChainPanel;
    16.  
    17.     Windows::UI::Xaml::Controls::SwapChainPanel^ WSACommonBridge::GetSwapChainPanel()
    18.     {
    19.         return _swapChainPanel;
    20.     }
    21.  
    22.     void WSACommonBridge::SetSwapChainPanel(Windows::UI::Xaml::Controls::SwapChainPanel^ panel)
    23.     {
    24.         _swapChainPanel = panel;
    25.     }
    26. }
     
  15. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Could you paste the error message?
     
  16. ClaytonOne

    ClaytonOne

    Joined:
    Sep 5, 2015
    Posts:
    89
    No error message other than the type / namespace declared in the winmd file is not found when you build
     
  17. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Is that error in Unity or exported Visual Studio project? If it's in Unity, can you upload the editor log?
     
  18. ArjunKPrahaladan

    ArjunKPrahaladan

    Joined:
    May 17, 2017
    Posts:
    13
    Hey, I don't know if this is off topic.
    Can somebody help me help me to create a webview Plugin for UWP so that I can display web pages in my application?
    PS: Already tried out Wwebview asset it uses a dated API and the website I am planning to load is not supported in it.
     
  19. GodzillaSpider

    GodzillaSpider

    Joined:
    Feb 21, 2018
    Posts:
    11
    Just wanted to say that I followed the procedure here and was able to pass data between *.xaml.cpp and my unity code. Thanks!