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
相关产品推荐
相关产品推荐

