【问题标题】:Calling Unity C# delegate from unmanaged code in a different thread (Android)从不同线程中的非托管代码调用 Unity C# 委托 (Android)
【发布时间】:2018-01-11 17:22:26
【问题描述】:

我将一个委托(日志记录函数)传递给非托管代码,它工作正常,除非它是从另一个线程调用的,它是 C++ 库的内部线程。 我阅读了this,但我找不到任何关于当涉及 C++ 线程时我应该期待什么的信息。这绝对是线程问题,因为当我从从 Unity 调用非托管函数的同一个线程调用它时,委托工作。

C#

public class SomeClass : MonoBehaviour 
{
    public delegate void LibLogHandler(int a);
    private LibLogHandler handlerDelegate;

    [DllImport ("mylibrary")]
    private static extern bool library_init (string arg1, string arg2, LibLogHandler logHandler);

    public void goNow()
    {
        this.handlerDelegate = new LibLogHandler (this.logHandler);
        bool res = library_init ("someArg1", "someArg2", this.handlerDelegate);
        Debug.Log ("library init: " + res);
    }

    void logHandler(int a)
    {
        Debug.Log ("[library] " + a);
    }
}

C++ 标头

extern "C" {

    typedef void (*LibLog) (int a);

    bool library_init(const char* arg1, const char* arg3, LibLog libLog);
}

C++ 源代码

static boost::asio::io_service IoService;
static boost::thread aThread;
static boost::shared_ptr<boost::asio::io_service::work> ThreadWork;

bool library_init(const char* arg1, const char* arg2, LibLog libLog)
{
#ifdef THREAD_ENABLED
    ThreadWork.reset(new boost::asio::io_service::work(IoService));
    aThread = boost::thread([](){
        IoService.run();
    });        
    IoService.dispatch([libLog]{
        libLog(100);
    });
#else
    libLog(10);
#endif
    return true;
}

因此,当THREAD_ENABLED 被定义时,应用程序会静默崩溃而没有其他信息。

【问题讨论】:

    标签: c# android c++ multithreading


    【解决方案1】:

    我发现了问题 - this article 有助于理解从本机插件调用的回调的特性。简而言之,在托管代码 (C#) 中,只需确保委托对象在一段时间内是持久的(引用的),同时可以从非托管代码中调用它。 无需担心使用GCHandle 固定内存,因为托管运行时环境会自动为委托对象创建一个非托管存根句柄,无论垃圾收集器操作如何,它都会维护其地址。这个存根句柄被传递给幕后的非托管函数。

    【讨论】:

      【解决方案2】:

      Unity 不支持线程,您不能在其他线程中使用它的 API。

      尝试使用

      bool res;
      try{
          res = library_init ("someArg1", "someArg2", this.handlerDelegate);
      }catch (System.Exception e){
          Debug.LogError(e.Message);
          throw;
      }
      

      找出你的线程有什么问题。

      编辑 我想知道我的第一个陈述在你的情况下是否属实。我认为 Debug.Log() 应该是安全的。如果是这种情况,您应该调试您的 C++ 线程并查看它崩溃的原因。

      【讨论】:

      • “Unity 不支持线程”是什么意思?一般来说,我认为情况并非如此。
      • Unity 不允许您从其他线程使用它的 API,即,如果您将 Unitys API 中的某些内容放入函数中并像您一样在委托中使用它 - 从另一个线程调用它可能会引发错误。但就像我在编辑中所说的那样。可能在您的情况下,这不是问题。尝试调试您的 C++ 代码,看看它为什么会崩溃。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-29
      • 2013-08-24
      • 1970-01-01
      • 2011-02-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多