Interop导致Unity崩溃

时间:2012-05-09 21:30:06

标签: c# c callback interop unity3d

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

我用Google搜索并发现this thread表示

  

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

     

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

     

(1)编写一个包装器来获取这些回调并对这些东西进行排队   然后公开一个允许统一请求下一个事件的函数/   数据对象或其他任何阻塞,无螺纹的形式(2)制作   callbacks调用一个静态函数来扩展   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();


    }
}

2 个答案:

答案 0 :(得分:4)

答案是

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

答案 1 :(得分:-5)

老兄的团结搞砸了。它可以随时崩溃,只需使用gnome。