互操作会导致 Unity 崩溃

本文关键字:Unity 崩溃 互操作 | 更新日期: 2023-09-27 18:33:52

是否可以

在 Unity 脚本中进行 C/C++ 函数回调,前提是您可以从脚本创建新线程?我试过了,但脚本执行后 Unity 就会崩溃。

我用谷歌搜索了一下,发现了这个线程,上面写着

Unity 不是回调也不是线程安全的,任何对类的访问 扩展 UnityEngine.Object 只允许来自同一线程 当 Unity 脚本运行时,而不是与其他线程异步 也不是来自 COM/OS 异步操作的异步回调

如果是这种情况,有两种可能的方法:

(1(编写一个包装器来获取这些回调并将内容排队,然后 然后公开一个函数,允许 Unity 请求下一个事件/ 数据对象或任何阻塞、非线程形式 (2( 使 回调调用从扩展的静态函数 System.Object 并编写与上述相同的逻辑来请求 有关扩展 UnityEngine.Object 的类的信息

但我认为如果我创建一个线程并回调到该线程中,那就没问题了,对吧?我之所以这样想,是因为我读过这样的线程,其中介绍了如何使 C 函数回调 C# 函数。所以我推断,如果我创建一个新线程,它不再是 Unity,它将只是单声道和 C#。

这是我使 Unity 崩溃的代码:

C++代码:

#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# 代码:

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();

    }
}

互操作会导致 Unity 崩溃

答案是肯定的!

我在 2012 年 8 月 8 日再次测试,使用 Unity 3.5.2f2,Pro 许可证。感谢您@hatboyzero的评论,我找到了这个例子。

虽然我问题中的代码不起作用,但以下代码有效:

// 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);
}

我不必像教程建议的那样嵌入MonoRuntime。只是上面的两段代码解决了我的问题。