【发布时间】:2020-08-30 01:30:32
【问题描述】:
上下文
几年前,我的公司构建了一个使用 C 库的 Objective-C 框架,现在我们正试图将其转换为 Swift。由于我们需要使用这个 C++ 库,我们需要维护这两种语言之间的互操作性,而不是从基础中完全消除 Objective-C 代码。 关键是我们需要以一种并非所有接口都对使用框架的应用程序可用的方式来做这件事——这就是我的问题所依赖的地方。
尝试
我搜索的第一件事是关于如何在 Swift 中使用 C++ 库,从我搜索的所有内容中,我们需要使用 Objective C 在 C++ 和 Swift 之间建立一座桥梁。所以我开始专注于尝试创建 swift 之间的互操作性和 Objective-C,而 C++ 库自然来自 C++ 和 Objective-C 之间的现有联系。
经过一千次谷歌搜索和 safari 标签后,我发现在 app 中,我们需要做的就是创建一个桥接头,然后我们就可以开始了,既不简单也不困难,但是有点麻烦,但是在框架内部我们没有桥接头,唯一可以实现的方法是ModuleMaps,这些家伙的行为就像在模块内封装了 ObjC 框架的桥接头。
所以我尝试了这个并且成功了!万岁!
但问题是:为了完成这项工作,我需要公开我的标题(以及我的新 swift 类)。所以更多的搜索出现了,我发现是Private module maps。 我试图从这样的教程中重新创建一个:
framework module MyDeprecatedObjCFramework {
umbrella header "MyDeprecatedObjCFramework.h"
export *
explicit module Private {
header "Path/To/Private/Header.h"
}
}
但是编译器没有考虑模块名称结尾处的 Private 关键字,我能够从框架外部访问它。为其设置名称也不起作用(例如MyDeprecatedObjCFrameworkPrivate 或MyDeprecatedObjCFramework_Private 或MyDeprecatedObjCFramework-Private,根据clang 文档,当前模式为_Private)。
分开创建一个文件并在构建设置中将其设置为Private Module Map 对我也不起作用,在这种情况下有两次尝试,第一次是这样的:
module MyDeprecatedObjCFramework_Private {
header "Path/To/Private/Header.h"
export *
}
在这种情况下,任何人都无法访问该模块,即使是在框架内部。简而言之,它没有被复制到Products Xcode 文件夹内的输出框架中。在module 之前添加关键字framework 导致include of non-modular header inside framework module。
我还发现这些 clang 的东西不够稳定,可能会在主要版本之间中断。从苹果本身来看,它似乎不是viable workaround,唯一的解决方案for this guy 是创建一个 lint 以防止外部应用程序导入私有标头/swift 类,这在我看来有点混乱。
最后一个问题
是否可以在框架内创建objective-c 和swift 之间的互操作性?这可行吗?从头开始重新创建整个框架会更好吗?还是拆分成其他swift框架比较好?
【问题讨论】:
标签: objective-c swift xcode language-interoperability module-map