互操作会导致 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();
}
}
答案是肯定的!
我在 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。只是上面的两段代码解决了我的问题。