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

Xcode 16 Swift与C++互操作:函数类型不匹配及符号重复定义问题

Xcode 16 Swift与C++互操作错误解决

问题背景

在Xcode 15中可正常运行的Swift与C++互操作代码,升级至Xcode 16后出现两个错误:

  1. 函数类型不匹配(声明与使用类型显示一致)
  2. 符号$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文件导致符号重复定义。

解决方法

  1. 防止头文件重复包含:所有C++头文件添加#pragma once或宏定义保护,避免重复导入:
#pragma once
// 或
#ifndef VIDEO_PROPERTIES_OBSERVER_H
#define VIDEO_PROPERTIES_OBSERVER_H
// 类定义
#endif
  1. 检查桥接文件:确保Objective-C桥接文件(Bridging-Header.h)中没有重复导入同一个C++头文件。
  2. 统一编译设置:在Xcode Build Settings中,确保所有Target的C++ Language Dialect(如C++17)、Enable C++ Interoperability设置一致。
  3. 检查重复链接:确认没有多个Target同时包含同一个C++源文件,导致符号重复生成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:20:18