andyman404 Posted October 24, 2018 Posted October 24, 2018 Has anyone had any success in getting the Viveport SDK for Unity to work with Unity's IL2CPP build option? I'm trying to integrate the Viveport SDK with my game, but when I build with the IL2CPP option and try to run it, I see this exception which prevents the Viveport API from trying to initialize: NotSupportedException: IL2CPP does not support marshaling delegates that point to instance methods to native code. at Viveport.Internal.Api.Init (Viveport.Internal.StatusCallback initCallback, System.String appId) [0x00000] in <00000000000000000000000000000000>:0 I don't get this issue when running within the editor, or if I run a build of game with the Mono build option - the SDK works fine for both of those. This issue only happens for IL2CPP, which is unfortunate, because the game has better performance when built with IL2CPP. I'm using Windows 10 Pro, 64-bit, Unity 2018.2.13f1, and Viveport SDK 1.7.10 (via the Unity package in the SDK). My code is pretty much just the example code in the SDK docs (but with my own VIVEPORT_ID obviously). This issue appears to be happening inside the internal API.Init method when it is trying to make the call to the DLL. Does anyone have any solutions/ideas, or is the Viveport SDK for Unity simple not compatible with the IL2CPP build option? If not, then how do we request for the Viveport SDK for Unity to support IL2CPP?
yakingkuo Posted November 1, 2018 Posted November 1, 2018 Hi : Please check below link. https://answers.unity.com/questions/1229036/callbacks-from-c-to-c-are-not-working-in-540f3.html Hope it can help you to fix this issue.
Chiranjeev Posted January 21, 2019 Posted January 21, 2019 Have you found a solution of it? i am stucked with the same problem
yakingkuo Posted January 23, 2019 Posted January 23, 2019 Hi Chiranjeev: Your issue can not be solved by the link? https://answers.unity.com/questions/1229036/callbacks-from-c-to-c-are-not-working-in-540f3.html Regards. Yaking
asdfqwer Posted March 2, 2019 Posted March 2, 2019 The provided link did not help I pasted the original Viveport for Unity code which runs fine in editor checking the license, but compiled to IL2CPP I also get NotSupportedException IL2CPP does not support marshaling delegates that point to instance methods to native code>ViveportApiInit (Viveport.StatusCallback callback, SYstem.Strng appId) (at <0000...0>:))ViveportLic.Start () (at <000...000>:0) The only thing I see that link does is adding [MonoPInvokeCallback(typeof(CallbackDelegate))] and that callback is already static. public class ViveportLic : MonoBehaviour {// ID and Key private delegate void CallbackDelegate(); void Start() { Api.Init(InitStatusHandler, VIVEPORT_ID); } [MonoPInvokeCallback(typeof(CallbackDelegate))] static void InitStatusHandler(int nResult) { Viveport.Core.Logger.Log("Init(): " + nResult); if (nResult != 0) { Viveport.Core.Logger.Log("Init setup error ..."); } UserStats.IsReady(IsReadyHandler); }
omkar_patil Posted April 16, 2019 Posted April 16, 2019 If some one is still stuck. I managed to create new script for few api operations for il2cpp support. using LitJson;using PublicKeyConvert;using System;using System.Collections;using System.Collections.Generic;using System.Runtime.InteropServices;using System.Security.Cryptography;using System.Text;using UnityEngine;public class ViveportIl2cpp : MonoBehaviour{ private static readonly List<GetLicenseCallback> InternalGetLicenseCallbacks = new List<GetLicenseCallback>(); private static readonly List<StatusCallback> InternalStatusCallbacks = new List<StatusCallback>(); internal static readonly List<LicenseChecker> InternalLicenseCheckers = new List<LicenseChecker>(); public static bool bInit = true, bIsReady = false, bArcadeIsReady = false, bTokenIsReady = false; static string APP_ID = "your app id"; static string APP_KEY = "Your app key"; [unmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void StatusCallback(int nResult); [unmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void GetLicenseCallback([MarshalAs(UnmanagedType.LPStr)] string message, [MarshalAs(UnmanagedType.LPStr)] string signature); [DllImport("viveport_api", EntryPoint = "IViveportAPI_Init", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] private static extern int Init(StatusCallback initCallback, string appId); [DllImport("viveport_api", EntryPoint = "IViveportAPI_GetLicense", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] private static extern void GetLicense(GetLicenseCallback callback, string appId, string appKey); [DllImport("viveport_api", EntryPoint = "IViveportUserStats_IsReady", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] private static extern int IsReady(StatusCallback IsReadyCallback); [DllImport("viveport_api", EntryPoint = "IViveportAPI_Shutdown", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] private static extern int Shutdown(StatusCallback initCallback); [DllImport("viveport_api", EntryPoint = "IViveportUser_GetUserID", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] internal static extern int GetUserID(StringBuilder userId, int size); [DllImport("viveport_api", EntryPoint = "IViveportUser_GetUserName", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] internal static extern int GetUserName(StringBuilder userName, int size); [DllImport("viveport_api", EntryPoint = "IViveportUser_GetUserAvatarUrl", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] internal static extern int GetUserAvatarUrl(StringBuilder userAvatarUrl, int size); [AOT.MonoPInvokeCallback(typeof(StatusCallback))] static void InitHandler(int nResult) { if (nResult == 0) { bInit = true; bIsReady = false; bArcadeIsReady = false; Viveport.Core.Logger.Log("InitStatusHandler is successful"); } else { // Init error, close your app and make sure your app ID is correct or not. bInit = false; Viveport.Core.Logger.Log("InitStatusHandler error : " + nResult); } } [AOT.MonoPInvokeCallback(typeof(StatusCallback))] static void ShutdownHandler(int nResult) { if (nResult == 0) { bInit = false; bIsReady = false; Viveport.Core.Logger.Log("ShutdownHandler is successful"); } else { Viveport.Core.Logger.Log("ShutdownHandler error: " + nResult); } } [AOT.MonoPInvokeCallback(typeof(StatusCallback))] static void IsReadyHandler(int nResult) { if (nResult == 0) { bIsReady = true; bArcadeIsReady = false; Viveport.Core.Logger.Log("IsReadyHandler is successful"); } else { // IsReady error, close your app and make sure the viveport is launched normally. bIsReady = false; Viveport.Core.Logger.Log("IsReadyHandler error: " + nResult); } } [AOT.MonoPInvokeCallback(typeof(GetLicenseCallback))] static void GetLicenseHandler( [MarshalAs(UnmanagedType.LPStr)] string message, [MarshalAs(UnmanagedType.LPStr)] string signature) { // Logger.Log("Raw Message: " + message); // Logger.Log("Raw Signature: " + signature); var isVerified = !string.IsNullOrEmpty(message); if (!isVerified) { for (var i = InternalLicenseCheckers.Count - 1; i >= 0; i--) { var checker = InternalLicenseCheckers[i]; checker.OnFailure(90003, "License message is empty"); InternalLicenseCheckers.Remove(checker); } return; } isVerified = !string.IsNullOrEmpty(signature); if (!isVerified) // signature is empty - error code mode { var jsonData = JsonMapper.ToObject(message); var errorCode = 99999; var errorMessage = ""; try { errorCode = int.Parse((string)jsonData["code"]); } catch { // ignored } try { errorMessage = (string)jsonData["message"]; } catch { // ignored } for (var i = InternalLicenseCheckers.Count - 1; i >= 0; i--) { var checker = InternalLicenseCheckers[i]; checker.OnFailure(errorCode, errorMessage); InternalLicenseCheckers.Remove(checker); } return; } isVerified = VerifyMessage(APP_ID, APP_KEY, message, signature); if (!isVerified) { for (var i = InternalLicenseCheckers.Count - 1; i >= 0; i--) { var checker = InternalLicenseCheckers[i]; checker.OnFailure(90001, "License verification failed"); InternalLicenseCheckers.Remove(checker); } return; } var decodedLicense = Encoding.UTF8.GetString( Convert.FromBase64String( message.Substring(message.IndexOf("\n", StringComparison.Ordinal) + 1) ) ); var jsonData2 = JsonMapper.ToObject(decodedLicense); Viveport.Core.Logger.Log("License: " + decodedLicense); var issueTime = -1L; var expirationTime = -1L; var latestVersion = -1; var updateRequired = false; try { issueTime = (long)jsonData2["issueTime"]; } catch { // ignored } try { expirationTime = (long)jsonData2["expirationTime"]; } catch { // ignored } try { latestVersion = (int)jsonData2["latestVersion"]; } catch { // ignored } try { updateRequired = (bool)jsonData2["updateRequired"]; } catch { // ignored } for (var i = InternalLicenseCheckers.Count - 1; i >= 0; i--) { var checker = InternalLicenseCheckers[i]; checker.OnSuccess(issueTime, expirationTime, latestVersion, updateRequired); InternalLicenseCheckers.Remove(checker); } } private static bool VerifyMessage( string appId, string appKey, string message, string signature) { try { var provider = PEMKeyLoader.CryptoServiceProviderFromPublicKeyInfo(appKey); var decodedSignature = Convert.FromBase64String(signature); var sha = new SHA1Managed(); var data = Encoding.UTF8.GetBytes(appId + "\n" + message); return provider.VerifyData(data, sha, decodedSignature); } catch (Exception e) { Viveport.Core.Logger.Log(e.ToString()); } return false; } public void SendLicenceStatus(bool isPassed, string message) { if (isPassed) { Debug.LogError("_________________passed__________________"); } else { Debug.LogError("_________________failed__________________"); } } // function to initialise public static void init_VivePort() { Init(InitHandler, APP_ID); if(bInit) { IsReady(IsReadyHandler); // after is ready you can fetch usern details from User.GetUserName(), User.GetUserId() } } // function to shutdown public static void ShutDown() { Shutdown(ShutdownHandler); } // function to get licence public static void GetViveLicenceStatus() { if(bIsReady && bInit) { MyLicenseChecker checker = new MyLicenseChecker(); InternalLicenseCheckers.Add(checker); GetLicense(GetLicenseHandler, APP_ID, APP_KEY); } }}public class MyLicenseChecker : LicenseChecker{ public delegate void LicenceCheck(bool passed, string message); public static event LicenceCheck OnCheck; public override void OnSuccess(long issueTime, long expirationTime, int latestVersion, bool updateRequired) { Viveport.Core.Logger.Log("[MyLicenseChecker] issueTime: " + issueTime); Viveport.Core.Logger.Log("[MyLicenseChecker] expirationTime: " + expirationTime); Viveport.Core.Logger.Log("[MyLicenseChecker] latestVersion: " + latestVersion); Viveport.Core.Logger.Log("[MyLicenseChecker] updateRequired: " + updateRequired); OnCheck(true, "Passed : (issueTime: " + issueTime + ")"); } public override void OnFailure(int errorCode, string errorMessage) { Viveport.Core.Logger.Log("[MyLicenseChecker] errorCode: " + errorCode); Viveport.Core.Logger.Log("[MyLicenseChecker] errorMessage: " + errorMessage); OnCheck(false, "Failed : (errorMessage: " + errorMessage + ")"); }}public abstract class LicenseChecker{ public abstract void OnSuccess( long issueTime, long expirationTime, int latestVersion, bool updateRequired ); public abstract void OnFailure( int errorCode, string errorMessage );}public partial class User{#if !UNITY_ANDROID private const int MaxIdLength = 256; private const int MaxNameLength = 256; private const int MaxUrlLength = 512;#endif public static string GetUserId() {#if !UNITY_ANDROID var userId = new StringBuilder(MaxIdLength); ViveportIl2cpp.GetUserID(userId, MaxIdLength); return userId.ToString();#else return Internal.User.GetUserId().ToString();#endif } public static string GetUserName() {#if !UNITY_ANDROID var userName = new StringBuilder(MaxNameLength); ViveportIl2cpp.GetUserName(userName, MaxNameLength); return userName.ToString();#else return Internal.User.GetUserName().ToString();#endif } public static string GetUserAvatarUrl() {#if !UNITY_ANDROID var userAvatarUrl = new StringBuilder(MaxUrlLength); ViveportIl2cpp.GetUserAvatarUrl(userAvatarUrl, MaxUrlLength); return userAvatarUrl.ToString();#else return Internal.User.GetUserAvatarUrl().ToString();#endif }} Hope this helps!
Recommended Posts
Archived
This topic is now archived and is closed to further replies.