You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中C#方法作为回调传递给Swift函数的崩溃问题排查

问题解决:Unity C#调用iOS Swift异步回调崩溃

核心问题在于Swift的@escaping闭包无法直接作为C兼容参数暴露,C语言无法识别Swift闭包的内存结构,直接传递会触发EXC_BAD_ACCESS内存访问错误。以下是修正方案:

1. 修改Swift桥接文件(Bridge.swift)

将回调参数改为C兼容的函数指针类型,再转换为Swift闭包使用:

import Foundation

// 定义C兼容的函数指针类型
typealias CBooleanCallback = @convention(c) (Bool) -> Void

@_cdecl("Example_returnTrue")
public func Example_returnTrue() -> Bool {
    print("Example_returnTrue started");
    return Example.returnTrue();
}

@_cdecl("Example_sendTrue")
public func Example_sendTrue(callback: CBooleanCallback) {
    print("Example_sendTrue started");
    // 将C函数指针转换为Swift闭包
    let swiftCallback: (Bool) -> Void = { value in
        callback(value)
    }
    Example.sendTrue(callback: swiftCallback)
}

2. 保持C#代码不变(iOSCommunication.cs)

你的C#代码已正确使用[MonoPInvokeCallback]特性,签名与C函数指针匹配,无需修改:

using System;
using UnityEngine;
using System.Runtime.InteropServices;
using AOT;

public class iOSCommunication : MonoBehaviour
{
    [DllImport("__Internal")]
    private static extern bool Example_returnTrue();

    [DllImport("__Internal")]
    private static extern void Example_sendTrue(Action<bool> callback);

    public void Start()
    {
        Debug.Log($"returnTrue: {Example_returnTrue()}");
        Example_sendTrue(ResultHandler);
    }

    [MonoPInvokeCallback(typeof(Action<bool>))]
    private static void ResultHandler(bool result)
    {
        Debug.Log($"sendTrue: {result}");
    }
}

关键原理说明

  • Swift闭包带有Swift Runtime的额外上下文信息,不属于C语言兼容类型,不能直接通过@_cdecl暴露给C调用。
  • @convention(c)标记的函数指针遵循C语言调用约定,与Mono生成的回调签名完全匹配,避免了内存访问错误。
  • 转换后的Swift闭包可安全传递给原有Example.sendTrue方法,实现异步回调逻辑。

运行修正后的代码,会看到Example_sendTrue started正常打印,且ResultHandler会收到回调值true。

内容的提问来源于stack exchange,提问作者Goldstein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 05:35:40