1 swift为啥没法直接c++混编 ,这样设置初衷是啥? 而oc就可以呢??
-
根本原因:语言设计的时代与目标不同
Objective-C:作为“C的超集”Objective-C 诞生于 1980 年代,其设计初衷就是为 C 语言添加面向对象的特性。它被设计为 C 的一个严格超集。
任何有效的 C 代码都是有效的 Objective-C 代码。编译器(Clang)首先会理解 C 的语法和类型系统,然后再其上添加 Objective-C 的语法和运行时。
由于 C++ 是从 C 发展而来的“近乎超集”,Objective-C 编译器天然就能理解 C++ 的语法(如类、模板、运算符重载等),只需一个特殊的编译模式 Objective-C++(文件扩展名为 .mm)。
Swift:作为“一门全新的现代语言”
Swift 诞生于 2010 年代,其设计目标是安全、高性能、表达力强且现代化。它完全摒弃了 C 的包袱(如指针算术、不安全的类型系统)。
Swift 拥有自己全新的类型系统、内存管理模型(自动引用计数 ARC)和语法,它与 C 或 C++ 没有血缘关系。Swift 编译器前端与 Clang(处理 C/C++/OC 的编译器)是独立的。
-
设计初衷与哲学
Objective-C 的初衷:渐进式改进它的存在就是为了让开发者能在已有的、庞大的 C 代码库基础上,逐步采用面向对象编程。与 C/C++ 无缝交互是其核心设计目标。
Swift 的初衷:革命性替代
Swift 的目标是提供一种更安全、更易用的语言来替代 Objective-C。其设计哲学是优先考虑安全性和清晰性,而非向后兼容所有 C 家族特性。
直接支持 C++ 会引入大量 C++ 的不安全特性和复杂性,这与 Swift 的安全第一(Safety by Default)的核心原则背道而驰。例如,C++ 的裸指针、手动内存管理和复杂的对象生命周期管理与 Swift 的强类型和自动内存管理模型格格不入。
2 假如用swiftUI开发 用到c++库 咋办??
其核心思想是通过 Objective-C++ (.mm 文件) 包装 C++ 代码,然后将 Objective-C 类暴露给 Swift。
示例
- TestC_hpp/TestC_hpp
#ifndef TestC_hpp
#define TestC_hpp
#include <stdio.h>
int multiplyByTwo(int value);
#endif /* TestC_hpp */
#include "TestC.hpp"
int multiplyByTwo(int value) {
return value * 2;
}
- CalculationWrapper.h 和 CalculationWrapper.mm
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface CalculationWrapper : NSObject
- (int)multiplyByTwo:(int)value;
@end
NS_ASSUME_NONNULL_END
#import "CalculationWrapper.h"
#import "TestC.hpp"
@implementation CalculationWrapper
- (int)multiplyByTwo:(int)value {
return multiplyByTwo(value);
}
@end
- SwiftCplusplusAdd-Bridging-Header.h
#import "CalculationWrapper.h"
- Swiftui
import SwiftUI
struct ContentView: View {
let calculator = CalculationWrapper()
@State private var result: Int = 0
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!\(result)")
Button("Multiply by") {
result = Int(calculator.multiply(byTwo:200))
}
}
.padding()
}
}
#Preview {
ContentView()
}
从 Swift 5.9 开始,苹果官方引入了与 C++ 互操作(C++ Interoperability)的能力。这允许 Swift 代码直接调用 C++ 代码,无需手动编写 Objective-C++ 包装器,但通常仍需要桥接头部
这种方式似乎不成熟,有些配置项还找不到.
3 在flutter又该如何呢??
在 Flutter 中与 C++ 混编主要是通过 Dart 的 FFI (Foreign Function Interface) 机制来实现的,这允许 Dart 代码直接调用 C/C++ 编译的原生库。另一种方式是使用 Platform Channel 进行间接调用。
1. 配置项目以编译 C++ 库
需要将 C++ 代码编译成平台相关的动态库(Android 上是 .so,iOS/macOS 上是 .a 或 .framework,Windows 上是 .dll,Linux 上是 .so)。
3.1 Android 平台 (使用 CMake):
放置源文件:将.hpp 和 .cpp 文件放在 Flutter 项目的 android/app/src/main/cpp 目录下
配置 CMakeLists.txt:在 android/app 目录下创建或修改 CMakeLists.txt 文件,指示如何编译 C++ 代码.
cmake_minimum_required(VERSION 3.4.1)
# 创建共享库
add_library(native-lib SHARED
src/main/cpp/my_native_lib.cpp)
# 包含头文件目录
include_directories(src/main/cpp/)
# 链接系统库
find_library(log-lib log)
target_link_libraries(native-lib ${log-lib})
配置 build.gradle:在 android/app/build.gradle 文件中启用 CMake。在flutter 3.19以上版本是 android/app/build.gradle.kts
externalNativeBuild {
cmake {
path = file("CMakeLists.txt")
}
}
// 在build.gradle 应该是
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}|
在 Dart 代码中加载并调用
ffi: ^2.1.4
import 'package:demo_01/ffi_demo.dart' show add, greetUser;
final result = add(5, 3);
// 测试字符串
final greetingPtr = greetUser('test');
Text('c++ add函数结果: $result'),
Text('greet函数结果: $greetingPtr')
3.2 在 Flutter iOS 推荐用 Platform Channel + Objective-C++,因为 FFI 目前对 iOS 下 C++ 支持有限。FFI只需要将c++代码导入iOS工程即可,比安卓简单一些。
注意拖入时弹窗里勾选 Runner target(Target Membership)。