异步接口托管 -> 非托管代码
Asynchronous interface managed -> umanaged code
我正在尝试实现从 C# Unity 到 C++ 的异步接口。
这是C++中公开的函数:
struct Vector3 {
float x;
float y;
float z;
};
extern "C" {
DLLEXPORT void sync_test(void*(Vector3[], int));
DLLEXPORT void async_test(void*(Vector3[], int));
}
它们是这样实现的:
void do_work(void*(onResult)(Vector3[], int)) {
int size = 30;
Vector3* result = new Vector3[size];
for (int i = 0; i < size; i++) {
result[i] = { 5,(float)i,2 };
}
onResult(result, size);
delete[] result;
}
DLLEXPORT void sync_test(void*(onResult)(Vector3[], int)) {
do_work(onResult);
}
DLLEXPORT void async_test(void*(onResult)(Vector3[], int)) {
std::thread thread(do_work, onResult);
}
这就是我在 C# 中使用它们的方式:
[DllImport("Isosurfaces.dll")]
static extern void async_test(Action<IntPtr, int> onResult);
[DllImport("Isosurfaces.dll")]
static extern void sync_test(Action<IntPtr, int> onResult);
// Use this for initialization
void Start () {
sync_test(OnResult);
//async_test(OnResult);
}
private void OnResult(IntPtr result, int size) {
Vector3[] tris = GetTris(result, size);
Debug.Log(tris[size - 1]);
}
Vector3[] GetTris(IntPtr result, int size) {
Vector3[] tris = new Vector3[size];
int vec3Size = Marshal.SizeOf(new Vector3());
for (int i = 0; i < size; i++) {
tris[i] = (Vector3)Marshal.PtrToStructure(new IntPtr(result.ToInt32() + (i * vec3Size)), typeof(Vector3));
}
return tris;
}
当 运行 项目统一时,sync_test
工作完美。打印的 Vector3 与在 C++ 端创建的 Vector3 匹配。
改为调用 async_test
时,Unity 会在没有错误消息的情况下关闭。查看 Editor.log
我看不到任何可能与关闭相关的信息。在同一文件夹中查看 upm.log
,我发现:
{"level":"error","message":"[Unity Package Manager (Upm)]\nParent process [12276] was terminated","timestamp":"2018-08-20T13:37:44.029Z"}
但这并没有给我太多关于发生的事情的背景。
我怀疑这与我的 C++ 代码有关。我已经有一段时间没有用 C++ 编程了,所以可能有些内存我忘记释放了。但截至目前,我看到我分配的唯一内存是 do_work
中的 Vector* result
并且在 C# 端处理完结果后立即释放。
编辑:在 do_work
中将 delete result
更改为 delete[] result
,但 Unity 仍然崩溃。
在 C++ 中释放内存:
Vector3* result = new Vector3;
delete result;
和
Vector3* result = new Vector3[size];
delete [] result;
您的 result
变量是一个数组,因此应该使用 delete [] result
async_test
创建 std::thread
对象,然后立即销毁,并在此过程中调用 std::thread::~thread()
。
根据 cppreference.com
, std::thread
destructor will call std::terminate()
if it has associated joinable 线程。
考虑将 thread.detach();
行添加到 async_test
,以便创建的线程不再附加到 std::thread
对象。
我正在尝试实现从 C# Unity 到 C++ 的异步接口。
这是C++中公开的函数:
struct Vector3 {
float x;
float y;
float z;
};
extern "C" {
DLLEXPORT void sync_test(void*(Vector3[], int));
DLLEXPORT void async_test(void*(Vector3[], int));
}
它们是这样实现的:
void do_work(void*(onResult)(Vector3[], int)) {
int size = 30;
Vector3* result = new Vector3[size];
for (int i = 0; i < size; i++) {
result[i] = { 5,(float)i,2 };
}
onResult(result, size);
delete[] result;
}
DLLEXPORT void sync_test(void*(onResult)(Vector3[], int)) {
do_work(onResult);
}
DLLEXPORT void async_test(void*(onResult)(Vector3[], int)) {
std::thread thread(do_work, onResult);
}
这就是我在 C# 中使用它们的方式:
[DllImport("Isosurfaces.dll")]
static extern void async_test(Action<IntPtr, int> onResult);
[DllImport("Isosurfaces.dll")]
static extern void sync_test(Action<IntPtr, int> onResult);
// Use this for initialization
void Start () {
sync_test(OnResult);
//async_test(OnResult);
}
private void OnResult(IntPtr result, int size) {
Vector3[] tris = GetTris(result, size);
Debug.Log(tris[size - 1]);
}
Vector3[] GetTris(IntPtr result, int size) {
Vector3[] tris = new Vector3[size];
int vec3Size = Marshal.SizeOf(new Vector3());
for (int i = 0; i < size; i++) {
tris[i] = (Vector3)Marshal.PtrToStructure(new IntPtr(result.ToInt32() + (i * vec3Size)), typeof(Vector3));
}
return tris;
}
当 运行 项目统一时,sync_test
工作完美。打印的 Vector3 与在 C++ 端创建的 Vector3 匹配。
改为调用 async_test
时,Unity 会在没有错误消息的情况下关闭。查看 Editor.log
我看不到任何可能与关闭相关的信息。在同一文件夹中查看 upm.log
,我发现:
{"level":"error","message":"[Unity Package Manager (Upm)]\nParent process [12276] was terminated","timestamp":"2018-08-20T13:37:44.029Z"}
但这并没有给我太多关于发生的事情的背景。
我怀疑这与我的 C++ 代码有关。我已经有一段时间没有用 C++ 编程了,所以可能有些内存我忘记释放了。但截至目前,我看到我分配的唯一内存是 do_work
中的 Vector* result
并且在 C# 端处理完结果后立即释放。
编辑:在 do_work
中将 delete result
更改为 delete[] result
,但 Unity 仍然崩溃。
在 C++ 中释放内存:
Vector3* result = new Vector3;
delete result;
和
Vector3* result = new Vector3[size];
delete [] result;
您的 result
变量是一个数组,因此应该使用 delete [] result
async_test
创建 std::thread
对象,然后立即销毁,并在此过程中调用 std::thread::~thread()
。
根据 cppreference.com
, std::thread
destructor will call std::terminate()
if it has associated joinable 线程。
考虑将 thread.detach();
行添加到 async_test
,以便创建的线程不再附加到 std::thread
对象。