How to call scripts from the xaml file in UWP IL2CPP?

It’s tricky. The engine and C# world are initializing on a different thread, so you’re not guaranteed that C# world even exists at this point in time. Furthermore, multiple activation requests can come in succession and you don’t want to lose any of them. I think the best solution here is to setup both a callback and multiple state storage. Something like this.

.cpp file in your Unity Project:

#include <string>
#include <vector>
#include <windows.h>

struct CriticalSection
{
    inline CriticalSection()
    {
        InitializeCriticalSectionAndSpinCount(&m_CriticalSection, 200);
    }

    inline ~CriticalSection()
    {
        DeleteCriticalSection(&m_CriticalSection);
    }

    inline void Enter()
    {
        EnterCriticalSection(&m_CriticalSection);
    }
  
    inline void Leave()
    {
        LeaveCriticalSection(&m_CriticalSection);
    }

    struct Lock
    {
        inline Lock(CriticalSection& criticalSection) :
            m_CriticalSection(criticalSection)
        {
            criticalSection.Enter();
        }

        inline ~Lock()
        {
            m_CriticalSection.Leave();
        }

    private:
        CriticalSection& m_CriticalSection;
    };

private:
    CRITICAL_SECTION m_CriticalSection;
};

typedef void(__stdcall* ActivatedEventCallback)(const wchar_t* uri);

static CriticalSection s_CriticalSection;
static std::vector<std::wstring> s_ActivationUriBacklog;
static ActivatedEventCallback s_ActivatedEventCallback;

extern "C" void __stdcall SetupActivatedEventCallback(ActivatedEventCallback callback)
{
    CriticalSection::Lock lock(s_CriticalSection);

    s_ActivatedEventCallback = callback;

    for (const auto& uri : s_ActivationUriBacklog)
        s_ActivatedEventCallback(uri.c_str());

    s_ActivationUriBacklog.clear();
}

__declspec(dllexport) void ReceivedResponse(const wchar_t* uri)
{
    CriticalSection::Lock lock(s_CriticalSection);

    if (s_ActivatedEventCallback != nullptr)
    {
        s_ActivatedEventCallback(uri);
    }
    else
    {
        s_ActivationUriBacklog.emplace_back(uri);
    }
}

And then on your Unity project side in C#, you’d do this:

        delegate void ReceivedResponseDelegate([MarshalAs(UnmanagedType.LPWStr)]string uri);

        [MonoPInvokeCallback(typeof(ReceivedResponseDelegate))]
        static void ReceivedResponse(string uri)
        {
            // Your code
        }

        [DllImport("__Internal")]
        extern static void SetupActivatedEventCallback(ReceivedResponseDelegate callback);

        void Awake()
        {
            SetupActivatedEventCallback(ReceivedResponse);
        }

Finally, on the VS side, you just have to declare and call that function:

__declspec(dllimport) void ReceivedResponse(const wchar_t* uri);
ReceivedResponse(eventArgs->Uri->ToString()->Data());
1 Like