What is causing the 'WrongThreadException' in Unity 3D? - c#

I want to integrate a C++ project in Unity. Unity provides a mechanism called I2CPP (Intermediate Language To C++) which allows to add C++ code to your unity project. I've created a simple C++ class and header in a "Blank App (Universal Windows C++/CX)" project in Visual Studio.
// header
namespace SomeNamespace {
public ref class MyRuntimeClass sealed
{
public:
// Constructor
MyRuntimeClass();
// Method to check if initialized
bool IsClassInitialized();
private:
bool _isRuntimeInitialized = false;
};
}
and
// implementation
using SomeNamespace;
MyRuntimeClass::MyRuntimeClass()
{
_isRuntimeInitialized = true;
}
bool MyRuntimeClass::IsClassInitialized()
{
return _isRuntimeInitialized;
};
I've made in Unity a simple project and made the necessary changes in the Player settings outlined in the documentation. I also added a cube as a game object and attached to the cube a script which uses my C++ code, i.e.
#if ENABLE_WINMD_SUPPORT
using SomeNamespace;
#endif
public class RuntimeSampleUnity : MonoBehaviour
{
#if ENABLE_WINMD_SUPPORT
private MyRuntimeClass _myRuntimeClass;
#endif
// Default MonoBehaviour method
void Start()
{
#if ENABLE_WINMD_SUPPORT
// New instance of runtime class
_myRuntimeClass = new MyRuntimeClass();
// Check to see if we initialized C++ runtime component
var isInit = _myRuntimeClass.IsClassInitialized();
Debug.LogFormat("MyRuntimeClass: {0}", isInit);
#endif
}
}
In a final step, I've added the winmd file from the C++ project to my assets in Unity. The project builds fine, but when I run the project I get an Platform.WrongThreadException: The application called an interface that was marshalled for a different thread. What is causing this exception (and how do I fix it)?
EDIT: To elaborate a bit why I'm doing what I'm doing: Microsoft provides a project which shows how to integrate OpenCV (C++) to HoloLens-based projects. While it provides a UWP project which mixes OpenCV and C#, it doesn't show how to integrate this particular project into Unity. Somebody actually made this possible via I2CPP. While I ran into issues using his Visual Studio 2017 based project into Visual Studio 2019, I've tried to make a minimal example to understand how it (basically) works.

I think you're misunderstanding the concept of IL2CPP.
IL2CPP (Intermediate Language To C++) is a Unity-developed scripting
backend which you can use as an alternative to Mono when building
projects for various platforms. When building a project using IL2CPP,
Unity converts IL code from scripts and assemblies to C++, before
creating a native binary file (.exe, apk, .xap, for example) for your
chosen platform. Some of the uses for IL2CPP include increasing the
performance, security, and platform compatibility of your Unity
projects.
To use C++ you have to write a Native Plugin.

Related

Problem with platform specific code in .NET MAUI and Jetbrains Rider

i am having the following problem. i try to invoke platform specific code in the .NET MAUI from the microsoft tutorial.
https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/invoke-platform-code
The problem here is that it can be compiled and builded with Visual Studio, but with Rider from Jetbrains it cant be compiled.
i m getting the following error message:
DeviceOrientationService.cs(5, 38): [CS8795] Partial method 'DeviceOrientationService.GetOrientation()' must have an implementation part because it has accessibility modifiers.
Anyone got an idea what i am missing?
So the thing is you need to create an implementation for your abstract method on all platform classes for it to be able to build since you are targeting multiple platforms.
So just like you have an implementation in your Android and iOS platforms you need it on others as well.
There is another way as well which is you can create an abstract method with an implementation that already does something on other platforms so assume this method is only relevant on Android and iOS then you would do something like below in this class:
public partial class DeviceOrientationService
{
#if ANDROID || IOS
public partial DeviceOrientation GetOrientation();
#else
public partial DeviceOrientation GetOrientation()
{
return DeviceOrientation.Undefiend;
}
#endif
}
Also if you don't want to support Tizen, Windows or MacCatalyst you can just remove their references from the csproj file and then you can delete their platform folders and you won't need to do the above-mentioned things at all your app will only expect Android and iOS code for the above project.

Console app in C# fails to execute as soon as data types in Autodesk libraries are used

I'm developing some AutoCAD add-ons in C# and I was hoping to work/debug my classes in a console application first until I'm ready to implement the functionality inside AutoCAD. /dot net libraries cannot be unloaded and one needs to restart/reload acad each time the code is modified/
Interestingly I'm finding that as soon as I declare a variable which uses an autocad data type my console app refuses to run and Im presented with a "the application is in break mode" screen in visual studio. For example this code does not run:
using System;
using Autodesk.AutoCAD.Geometry;
namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hi");
Point2d p;
Console.ReadKey();
}
}
}
Trying this referencing Autodesk C3D 2016 dll libraries. Does anyone have an explanation of what is going on here and/or any workarounds?
thnks
The AutoCAD .NET API is designed to run in-process only.
AutoCAD .NET libraries can only be used to build plug-ins (DLL) which have to be loaded in AutoCAD for execution.
To debug your AutoCAD Add-On code, you need to create a C# Class Library Project referencing the Autodesk CAD 2016 Sdk Libraries, and encapsulate your code on public method that declared with CommandMethodAttribute. With this method declared with CommandMethod it's the be your trigger between the AutoCAD prompt command and your Add-On code.
public class AcadCommands
{
[CommandMethod("TriggerCmd")]
public void TriggerCommand
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage("Hi");
Point2d p;
}
}
Note: at your Visual Studio Project Properties, you need to configure to start debug pointed to acad.exe and when the AutoCAD applications starts, open some DWG and prompt the "NETLOAD" command to include your debbugable compiled DLL from your VS Project to AutoCAD Application context.

How to add Text to Speech to Unity project?

I am looking for System.speech to work in unity? Is there any way how to include this DLL in unity and MonoDevelop?
Because I'm trying to make a sound text to speech without spend the money from asset store. If System.Speech Library DLL could handle this why not. Just how to make it work with unity 5.3.5 ?
Also I have already try speechLib.dll. It is work while in editor but when Build to APK it is error and can't build.
Dlls files don't work on Android or iOS unless it is an unmanaged dll file without Windows specified API. If it is a Windows API or a managed dll then it won't work on Android or iOS.
You have two options: Buy a plugin or make your own. If you are only targeting Android and iOS then go for this Easy TTS which cost $5.
If you want to make one yourself then the process is very similar to my Speech to Text solution. The only difference are the classes used. Making one your self is easy. The only downside is that it is time consuming to make one for each platform.
Android:
TextToSpeech class.
iOS:
AVSpeechSynthesizer class
MacOS:
NSSpeechSynthesizer class
Windows:
ISpVoice class
There are tons of examples of how to use these on the internet. You have to make plugin for the Android class using Java, Objective-C for the iOS and MacOs classes. C++ for the Windows class.
For putting them together, you should use Unity's directive to do that.
class TextToSpeech
{
#if UNITY_ANDROID
Use TextToSpeech class
#endif
#if UNITY_IOS
Use AVSpeechSynthesizer class
#endif
#if UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX
Use NSSpeechSynthesizer class
#endif
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
Use ISpVoice class
#endif
}

Unity3D is not loading this .NET library, with no obvious reason why

I'm trying to get a third party SDK working with Unity. Here's a download of the files in said SDK: https://dl.dropboxusercontent.com/u/11217331/VSDK.zip
The "_DotNET.dll" is a .NET wrapper for the unmanaged code in the CPP dll. For some reason, Unity doesn't load the .NET dll whatever I try:
I put both DLLs in the Assets/Plugins folder
I am using Unity Pro 4.5.0f6, on Windows 8.1
The SDK "_DotNET.dll" is x86 .NET 2.0, and seems to be completely compatible with Unity's version of Mono
I tried putting both DLLs in the Program Files/Unity/Editor folder, still doesn't load them
I do not have the source to these DLLs so I can't make any changes to them, but everything points at Unity being weird here
There are no errors in the editor log or anywhere that give me a hint to why Unity just completely ignores these DLLs
If you can get this C# script working in Unity by loading these DLLs, please tell me your secrets:
using UnityEngine;
using System.Collections;
using ViconDataStreamSDK;
public class test : MonoBehaviour {
ViconDataStreamSDK.DotNET.Client e;
void Start () {
bool isConnected = e.IsConnected().Connected;
Debug.Log("Is it connected?: " + isConnected.ToString());
}
void Update () {
}
}
Ok, it seems I can load it by going back one Unity version, to 4.3.4f1. No idea why, culprit must be somewhere in the Unity 4.5 patch notes (http://unity3d.com/unity/whats-new/unity-4.5).
You will probably need to put the source code for the C# plugin into the unity and see what actual errors it gives you.

Unable to cast a class implementing and interface to this interface in IronPython and C#

I'm trying to write a scripting engine to my C#/XNA game using IronPython and came across a problem.
public class Game1 : Game, IGFXEnabledGame
{
//stuff
}
In the Game1 constructor I do necessary initialization for script and then run it to create the Camera object. I try to move the following hard-coded Camera initialization to a script:
CCamera camera = new CFPPCamera(this);
CCamera is an abstract class and CFPPCamera inhertits from it. CFPPCamera has the following constructor:
public CFPPCamera(Game game)
: base(game)
{
}
Script initialization:
InitScriptPath = "InitScript.py";
rootDir = AppDomain.CurrentDomain.BaseDirectory;
scriptDir = Path.Combine(rootDir, "Scripts");
scriptEngine = Python.CreateEngine();
scriptRuntime = scriptEngine.Runtime;
scriptScope = scriptRuntime.CreateScope();
scriptSource = scriptEngine.CreateScriptSourceFromFile(Path.Combine(scriptDir, InitScriptPath));
scriptScope.SetVariable("this", this);
scriptSource.Execute(scriptScope);
Script code:
import clr
clr.AddReference('Microsoft.Xna.Framework')
clr.AddReference('Microsoft.Xna.Framework.Game')
clr.AddReferenceToFile("../../../../../GFXEngine/bin/x86/Debug/GFXEngine.dll")
import Microsoft.Xna.Framework
from GFXEngine.GFX.Camera import *
from GFXEngine.GFX import *
camera = CFPPCamera(this);
The code compiles without warnings or errors, however on script execution I get an error:
Unable to cast object of type 'RenderingStreamTesting.Game1' to type GFXEngine.GFX.IGFXEnabledGame'.'
If I don't pass the Camera generation to the script, everything works fine.
RenderingStreamTesting and GFXEngine are two projects in the same solution, with RenderingStreamTesting being the base game project that GFXEngine references.
From what I found the problem might be caused by referencing different assemblies. I double checked and all references are made to native .NET .dlls and all third party libraries are listed in common directory.
What am I missing?
It's probably the AddReferenceToFile call. Most likely you're ending up with the same assembly loaded into multiple loader contexts. If XNA is in the GAC I would recommend putting GFXEngine in the GAC or putting it in the same directory as the entry point EXE and use AddReference. That way everything should get loaded into the same context.
Might the IronPython script end up being compiled as "Any CPU" IL (perhaps if your running this on a x64 OS)?
I've experienced problems with this where my app assembly was set to target the "Any CPU" platform while my XNA library targets x86. Changing the platform on the app assembly to x86 also solved the problem.
I'm unsure though whether it is possible to control the platform setting in an IronPython project.

Categories

Resources