背景
Swift project 中 c/c++
混编一般可以通过创建 bridging-header.h
文件来完成, 然而如果是在 framework
中这种操作是不被准许的, 即使是在 executable target
中虽然能完成集成但是也十分不优雅
方案
使用 modulemap
是目前解决此类问题的主要途径, 包括c/c++/Objective-c
混编. 关于 modulemap
的介绍可以参考 apple 的官方文档(点我直达). 另外在实际使用中, 我们一般会通过 git submodule
来将需要混编的 libs
集成到项目
使用
-
集成
libs
直接将需要集成的 libs
丢进项目
-
创建
module.modulemap
文件
在工程中创建 module.modulemap
文件 (这里直接在 excutable target
下创建) 选择新建 empty
, 文件名填写 module.modulemap
- 编辑
module.modulemap
文件
module Unsafe [system] [extern_c] {
header "../lib/include/unsafe-header.h"
export *
}
module SomeModule [system] [extern_c] {
header "PATH_FOR_HEADER"
export *
}
Warning: Unsafe
是 module name
, header
的 path
是 module.modulemap
的实体路径(不是 xcode 中看到的虚拟路径)的相对路径
, 否则会报错找不到头文件, Copy Bundle Resources
中不能添加 module.modulemap
文件, 否则第二次编译会报错 Redefinition module
-
工程配置
- 方法一: 通过
Configuration Settings File
无疑是最简单的, 这里不做赘述 - 方法二:
Build Settings -> Import Paths
填写$(SRCROOT)/Modulemap
(当前target
文件夹路径), 如果libs
源码导入, 报错各种头文件找不到, 可以设置下Building Settings -> Header Search Paths
->$(SRCROOT)/Modulemap/lib/include/
- 方法一: 通过
结束
到这里整个集成便完成了(这里是demo)
注意: 有些 c/c++ source code
的编写风格可能对编译器不友好, 导致实际调用的时候报错, 比如 c++
的 bool
类型, 头文件没有直接暴露 struct
的具体实现(只是提供了声明), 这就需要对 source code
进行改动.
另外 Swift
不支持直接与 Cpp
混编(调用), 实际是通过 C
来完成, 因此 C
的 header File
通常要添加如下声明
#ifdef __cplusplus
extern "C" {
#endif
void entry(); /* Your functions or variables */
#ifdef __cplusplus
}
#endif