Swift调用C++函数
Swift调用C++函数
背景(可略过)
字节跳动青训营要求写一个华容道游戏,实现 一键求解 的功能。刚开始用Swift写了个暴力的BFS,但是实在是太慢了,我觉得可能是Swift效率太低造成的,所以就想用C++写这个BFS。就这样,我的折磨旅途开始了。
概述
总体来说,Swift调用C++函数的步骤如下:
- 写好C++函数
- 使用Objective-C把C++函数封装一层
- 将Objective-C封装好的函数桥接到Swift
- 在Swift中调用前,做好类型转化
具体操作
这里就以我的华容道为例子了。
项目结构如下
其中主要关注**CppSolver.hpp CppSolver.cpp CppWrapper.h CppWrapper.mm Klotski-Bridging-Header.h **即可,这是在Swift调用C++函数中起到关键作用的文件。
1.写好C++函数
CppSolver.hpp如下
#ifndef CppSolver_hpp
#define CppSolver_hpp
#include <stdio.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
int getNum(int x);
char *solveGame(char *gameString);
#ifdef __cplusplus
}
#endif
#endif /* CppSolver_hpp */
注意这里的extern "C"
之前没有加这个,一直报错,上网搜了之后,发现要加上这个。
CppSolver.cpp如下
#include "CppSolver.hpp"
char *solveGame(char* gameString) {
/*
Do Something
*/
return "hahahah";
}
2.使用Objective-C封装C++函数
CppWrapper.h如下
#ifndef CppWrapper_h
#define CppWrapper_h
#import <Foundation/Foundation.h>
struct CppStruct;
@interface CppWrapper: NSObject
- (char *) solveGame_Wrapped: (NSString *) gameString;
@end
#endif /* CppWrapper_h */
CppWrapper.mm如下
#import <Foundation/Foundation.h>
#import "CppWrapper.h"
#import "CppSolver.hpp"
@implementation CppWrapper
- (int) getNum_Wrapped: (int)x {
// struct CppStruct *cs = CppStruct(1, 2);
return getNum(x);
}
- (char *) solveGame_Wrapped: (NSString *) gameString {
return solveGame([gameString UTF8String]);
}
@end
3.把Objective-C封装好的C++函数桥接到Swift
在创建Objective-C文件时,Xcode会提醒是否要建立桥接文件,这里我们要选择是,也就是创建了Klotski-Bridging-Header.h:
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "CppWrapper.h"
4.在Swift中调用Objective-C函数
注意做好类型转换
func solveByPersonControllers(_ personControllers: [PersonController]) {
let game = GameStatusForCpp(personControllers: personControllers)
guard let gameData = try? JSONEncoder().encode(game) else {
fatalError("unexpected game status \(game)")
}
guard let gameString = String(data: gameData, encoding: .utf8) else {
fatalError("unexpected gameData \(gameData)")
}
let cppWrapper = CppWrapper()
guard let solveChars = cppWrapper.solveGame_Wrapped(gameString) else { fatalError() }
guard let solveStr = String(cString: solveChars, encoding: .utf8) else { fatalError() }
print(solveStr)
}
建议
建议需要用到复杂的数据类型(类、结构体)的时候,可以传递json字符串(我上面的代码就是这样做的),因为我暂时还没找到更好的方法可以让Swift和C++使用共同的结构。至于C++的json处理,有一个比较好用的库,是腾讯的rapidjson。
C++的返回值类型应该需要是Objective-C和Swift里都有的类型
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!