【问题标题】:Interop causes Unity to crash互操作导致 Unity 崩溃
【发布时间】:2012-05-09 21:30:05
【问题描述】:

是否有可能将 C/C++ 函数回调到 Unity 脚本中,前提是您可以从脚本创建一个新线程?我试过了,但是一旦脚本执行,Unity 就会崩溃.

我在 Google 上搜索了一下,发现 this thread 上面写着

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

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

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

但我认为如果我创建一个线程并回调到该线程中,就可以了,对吧?我这样想是因为我读过像 this one 这样的线程,它介绍了如何制作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();


    }
}

【问题讨论】:

  • 您是否考虑过您遇到的崩溃是否是由于在将字符串传递回 C# (Unity) 之前未在 C++ 中编组字符串(即使用 'mono_string_new()' - 请参阅 @ 987654323@)?

标签: c# c callback interop unity3d


【解决方案1】:

答案是是的

我在 2012 年 8 月 8 日再次测试,使用 Unity 3.5.2f2,Pro 许可证。感谢@hatboyzero 的评论,我发现this example

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

// 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。只是上面两段代码解决了我的问题。

【讨论】:

  • 我几乎做了同样的事情,但我仍然看到崩溃。我没有添加两个变量,而是尝试创建一个新纹理,但我认为创建纹理需要在渲染线程中运行。我该怎么做?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-04
  • 2014-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多