在垃圾短信过滤应用 SMSFilters 中,需要使用 Jieba 分词库来対短信进行分词,然后使用 TF-IDF 来进行处理` 分词库是 C++ 写的,这就意味着需要在Swift中集成 C++ 库。
在官方文档 "Using Swift with Cocoa and Objective-C" 中,Apple只是介绍了怎么将 Swift 代码跟 Objective-C 代码做整合,但是没有提C++,后来在官方文档中看到了这样一段话:
You cannot import C++ code directly into Swift. Instead, create an Objective-C or C wrapper for C++ code.
也就是不能直接导入 C++ 代码,但是可以使用 Objective-C 或者 C 对 C++ 进行封装。所以项目中使用 Objective-C 做封装,然后在 Swift 中调用,下面就是这个过程的实践,Demo 代码见 SwiftJiebaDemo。
warning: include path for stdlibc++ headers not found; pass '-std=libc++' on the command line to use the libc++ standard library instead [-Wstdlibcxx-not-found]
Build Setting -> C++ Standard Library -> libstdc++ 修改为 Build Setting -> C++ Standard Library -> libc++
在垃圾短信过滤应用
SMSFilters
中,需要使用Jieba
分词库来対短信进行分词,然后使用TF-IDF
来进行处理` 分词库是 C++ 写的,这就意味着需要在Swift中集成 C++ 库。 在官方文档 "Using Swift with Cocoa and Objective-C" 中,Apple只是介绍了怎么将 Swift 代码跟 Objective-C 代码做整合,但是没有提C++,后来在官方文档中看到了这样一段话:也就是不能直接导入 C++ 代码,但是可以使用 Objective-C 或者 C 对 C++ 进行封装。所以项目中使用 Objective-C 做封装,然后在 Swift 中调用,下面就是这个过程的实践,Demo 代码见 SwiftJiebaDemo。
整合过程
分成三步:
引入C++文件
Demo中使用的是"结巴"中文分词的 C++ 版本 yanyiwu/cppjieba。将其中的
include/cppjieba
和依赖limonp
合并,并加入dict
中的hmm_model
和jiaba.dict
作为基础数据,并暴露JiebaInit
和JiebaCut
接口:以及
目录如下:
接下来开始在项目中集成。首先创建一个空项目
iOSJiebaDemo
,将iosjieba
加入项目中。添加 iosjieba:
见代码: https://github.com/qiwihui/SwiftJiebaDemo/commit/caeb6c2f9fb005a9bc518ee67890814481676807
C++ 到 Objective-C 封装
这个过程是将 C++ 的接口进行 Objective-C 封装,向 Swift 暴露。这个封装只暴露了
objcJiebaInit
和objcJiebaCut
两个接口。见代码: https://github.com/qiwihui/SwiftJiebaDemo/commit/7d196bb2c33280a4f419be21b47961a521618221
Objective-C 到 Swift
在 Swift 中调用 Objecttive-C 的接口,这个在官方文档和许多博客中都有详细介绍。
{project_name}-Bridging-Header.h
头文件,即SwiftJiebaDemo_Bridging_Header_h
,引入之前封装的头文件,并在Targets -> Build Settings -> Objective-C Bridging Header
中设置头文件路径SwiftJiebaDemo/SwiftJiebaDemo_Bridging_Header_h
。.m
改为.mm
:iosjiebaWrapper.m
改为iosjiebaWrapper.mm
。见代码:https://github.com/qiwihui/SwiftJiebaDemo/commit/94852b1357b0a0a4b2e8b92384fbdb1b16c80ed8
使用
使用时需要先初始化
Jiaba
分词,然后再进行分词。控制台输出结果:
可以看到,测试用例
小明硕士毕业于中国科学院计算所,后在日本京都大学深造
经过分词后为〔拼音〕["小明", "硕士", "毕业", "于", "中国科学院", "计算所", ",", "后", "在", "日本", "京都大学", "深造"]
,完成集成。见代码: https://github.com/qiwihui/SwiftJiebaDemo/commit/bc42e1312dff6a9f7171cc69403136bc8a82204c
遇到的问题
由于自己对于编译链接原理不了解,以及是 iOS 开发初学,因此上面的这个过程中遇到了很多问题,耗时两周才解决,故将遇到的一些问题记录于此,以便日后。
"cassert" file not found
将
.m
改为.mm
即可。compiler not finding <tr1/unordered_map>
设置
C++ Standard Library
为LLVM libc++
参考: mac c++ compiler not finding <tr1/unordered_map>
warning: include path for stdlibc++ headers not found; pass '-std=libc++' on the command line to use the libc++ standard library instead [-Wstdlibcxx-not-found]
Build Setting -> C++ Standard Library -> libstdc++
修改为Build Setting -> C++ Standard Library -> libc++
use of unresolved identifier
这个问题在于向项目中加入文件时,
Target Membership
设置不正确导致。需要将对于使用到的 Target 都勾上。相关参考: Understanding The "Use of Unresolved Identifier" Error In Xcode
参考