Xcode 16 Swift与C++互操作:函数类型不匹配及符号重复定义问题
Xcode 16 Swift与C++互操作错误解决
问题背景
在Xcode 15中可正常运行的Swift与C++互操作代码,升级至Xcode 16后出现两个错误:
- 函数类型不匹配(声明与使用类型显示一致)
- 符号
$sSo1soiySiSo3stdO3__1O0036___wrap_iterUnsafePointer__DgGIinaBdaV_AGtFTO存在多个定义
原代码如下:
C++代码
class VideoPropertiesObserver { public: void (*updateOperationModeUI)(VideoCutterOperationMode) = nullptr; void setOperationModeObserver(void (*fun)(VideoCutterOperationMode)) { updateOperationModeUI = fun; } };
Swift代码
public class VideoCutterModuleManager{ public init(delegate : CppUpdateDelegate) { VideoCutterModuleManager.sharedInstance = self setObservers() } private func setObservers() { manager.setupVideoPropertiesObserver(); manager.videoPropertiesObserver.setOperationModeObserver(updateOperationModeUI) } private let updateOperationModeUI: @convention(c) (VideoCutterOperationMode) -> Void = { mode in VideoCutterModuleManager.sharedInstance?.delegate?.updateOperationModeUI(mode: mode) } }
错误1:函数类型不匹配
原因
Xcode 16对Swift与C++互操作的函数类型校验更严格,原Swift代码中@convention(c)闭包捕获了sharedInstance上下文,而C函数指针不允许携带捕获的上下文,此前Xcode 15未严格限制该问题。
解决方法
修改C++观察者的函数指针定义,增加上下文参数,避免Swift闭包捕获变量:
修改后的C++代码
class VideoPropertiesObserver { public: void (*updateOperationModeUI)(VideoCutterOperationMode, void*) = nullptr; void* observerContext = nullptr; void setOperationModeObserver(void (*fun)(VideoCutterOperationMode, void*), void* ctx) { updateOperationModeUI = fun; observerContext = ctx; } // 调用通知时需传入上下文 void notifyOperationModeChange(VideoCutterOperationMode mode) { if (updateOperationModeUI != nullptr && observerContext != nullptr) { updateOperationModeUI(mode, observerContext); } } };
修改后的Swift代码
public class VideoCutterModuleManager{ public static var sharedInstance: VideoCutterModuleManager? public let delegate: CppUpdateDelegate public init(delegate : CppUpdateDelegate) { self.delegate = delegate VideoCutterModuleManager.sharedInstance = self setObservers() } private func setObservers() { manager.setupVideoPropertiesObserver() // 传递当前实例作为上下文 manager.videoPropertiesObserver.setOperationModeObserver(updateOperationModeUI, Unmanaged.passUnretained(self).toOpaque()) } private let updateOperationModeUI: @convention(c) (VideoCutterOperationMode, UnsafeMutableRawPointer?) -> Void = { mode, ctx in // 从上下文恢复实例 guard let ctx = ctx, let manager = ctx.assumingMemoryBound(to: VideoCutterModuleManager.self).pointee else { return } manager.delegate.updateOperationModeUI(mode: mode) } }
错误2:符号存在多个定义
原因
通常由C标准库模板重复导入、链接,或多Target共享C文件导致符号重复定义。
解决方法
- 防止头文件重复包含:所有C++头文件添加
#pragma once或宏定义保护,避免重复导入:
#pragma once // 或 #ifndef VIDEO_PROPERTIES_OBSERVER_H #define VIDEO_PROPERTIES_OBSERVER_H // 类定义 #endif
- 检查桥接文件:确保Objective-C桥接文件(Bridging-Header.h)中没有重复导入同一个C++头文件。
- 统一编译设置:在Xcode Build Settings中,确保所有Target的
C++ Language Dialect(如C++17)、Enable C++ Interoperability设置一致。 - 检查重复链接:确认没有多个Target同时包含同一个C++源文件,导致符号重复生成。
内容的提问来源于stack exchange,提问作者Dipon
相关产品推荐
相关产品推荐

