Interop Crashes Unity

Is it even possible to make a callback to the C / C ++ function in Unity scripts, provided that you can create a new thread from the scripts? I tried, but Unity crashes as soon as the scripts are executed.

I thought it over and found this thread that says

Unity is not a callback, nor thread safe, nor access to classes that the UnityEngine.Object extension is allowed from only one thread since unity scripts are run and not asynchronous from other threads nor from asynchronous callbacks from asynchronous COM / OS operations.

If this is for you there are two possible ways:

(1) Write a wrapper that receives these callbacks and queues things and then set up a function that allows the unit to request the next event / dataobject or something else in a blocking, incomplete form (2) Make callbacks call a static function on something- then System.Object and write the same logic as above to request information about classes extending UnityEngine.Object

But I think that if I create a thread and a callback to this thread, will everything be okay? I think so because I read streams such as this one that describes how to execute C functions that return C # functions. Therefore, I decided that if I create a new thread, it is no longer Unity, it will be just mono and C #.

Here is my code that breaks Unity:

C ++ Code:

#include <iostream> // #include "stdafx.h" typedef int (__stdcall * Callback)(const char* text); Callback Handler = 0; extern "C" __declspec(dllexport) void __stdcall SetCallback(Callback handler) { Handler = handler; } extern "C" __declspec(dllexport) void __stdcall TestCallback() { int retval = Handler("hello world"); } 

C # code:

 using UnityEngine; using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; class UnManagedInterop : MonoBehaviour { private delegate int Callback(string text); private Callback mInstance; // Ensure it doesn't get garbage collected public void Test() { mInstance = new Callback(Handler); SetCallback(mInstance); TestCallback(); } private int Handler(string text) { // Do something... print(text); return 42; } [DllImport("test0")] private static extern void SetCallback(Callback fn); [DllImport("test0")] private static extern void TestCallback(); void Start() { Thread oThread = new Thread(new ThreadStart(Test)); // Start the thread oThread.Start(); } } 
+6
source share
2 answers

Answer Yes !

I tested again on August 8, 2012 with a Unity 3.5.2f2, Pro license. Thanks for the comment by @hatboyzero. I found this example .

Although the code in my question does not work, the following code works:

 // C# using System.Runtime.InteropServices; class Demo { delegate int MyCallback1 (int a, int b); [DllImport ("MyRuntime")] extern static void RegisterCallback (MyCallback1 callback1); static int Add (int a, int b) { return a + b; } static int Sub (int a, int b) { return a - b; } void Init () { // This one registers the method "Add" to be invoked back by C code RegisterCallback (Add); } } // C typedef int (*callback_t) (int a, int b); static callback_t my_callback; void RegisterCallback (callback_t cb) { my_callback = cb; } int InvokeManagedCode (int a, int b) { if (my_callback == NULL){ printf ("Managed code has not initialized this library yet"); abort (); } return (*my_callback) (a, b); } 

I did not need to embed MonoRuntime, as the tutorial suggests. Only these two pieces of code solved my problem.

+4
source

The only dude spoiled. It may crash at any time, just use gnome.

-5
source

Source: https://habr.com/ru/post/915334/


All Articles