如何将C代码编译到Swift框架中

用户名

我有一个Swift框架,我们可以对其进行编译并分发给第三方开发人员。我想在项目中包含一些C代码,但使它起作用的唯一方法是将C标头导入框架的标头并将C标头设置为public。这会将所有C代码公开给第三方开发人员,这不是我们想要的。

我在网上可以找到的所有有关此方法的信息都是该方法的一种变体:https : //spin.atomicobject.com/2015/02/23/c-libraries-swift/

但是此方法的警告是“请注意,使用此技术构建的任何框架的使用者也都必须将模块添加到他们的Swift搜索路径中。” 并且我们已经尝试了这一点,并且确定我们的第三方开发人员肯定会得到一个错误Missing required module 'CGeodesic'该错误是我们定义的指向C标头的模块。

我们如何才能将C代码直接编译到我们的框架中,同时保持代码的私密性,又不要求第三方开发人员更改其构建设置才能使其正常工作呢?我不介意在我们的项目中设置这些子模块,但是最终,我希望将其直接编译成单个平面框架二进制文件,而不需要动态链接或搜索路径或类似的东西。

编辑


该项目是与Swift代码并排的C代码。我的项目中有一个子目录,如下所示:

  • 测地线/
    • 测地线
    • 测地线
    • 测地线

Swift文件包装了C代码,使其更整洁地工作。我在该目录中也有一个module.modulemap文件,但是就像我之前说的那样,它不起作用。我宁愿将C代码与我的Swift代码并排放置,但我愿意为了解决这个问题而放弃。

詹斯·梅德(Jens Meder)

只是为了重述您的问题:您基本上想将C代码包装在Swift中,并防止直接访问封装的C代码。这意味着要防止从Swift以及Objective-C进行访问。

这是可能的,但是需要对构建过程进行一些调整,并进行一些后期处理。

框架中的C和Swift互操作

您想要包装在Swift中的所有C代码都必须在编译期间通过伞标头或使用模块映射公开。这里的重要部分:在编译时框架没有完整性检查,这意味着您可以对其进行后处理(例如,使用创建一个胖二进制框架lipo)。这就是我们在这里需要做的。

准备构建

除了将所有C标头依赖项放入伞形标头之外,您还可以将它们放入module.modulemap文件中。这有一个优点:您可以在Headers构建阶段将标头设为私有

因此,请module.modulemap在您的项目中创建一个文件,然后Module Map File在该Packaging部分的“构建”设置MODULEMAP_FILE在xcconfig文件中)中设置其路径,例如$(SRCROOT)/MyFramework/module.modulemap

您的module.modulemap文件应具有以下内容:

# module.modulemap

framework module MyFramework {

    umbrella header "MyFramework.h"  

    export *
    module * {export *}

    # All C Files you want to wrap in your Swift code

    header "A.h"
    header "B.h"
}

到现在为止还挺好。现在,您应该能够构建代码并从Swift和Objective-C对其进行访问。唯一的问题:您仍然可以在Swift和Objective-C中访问C头文件。

后期处理

如果查看最终的Framework捆绑包,您会注意到所有私有头文件都已复制到该MyFramework.framework/PrivateHeaders文件夹中。这意味着您仍然可以通过#import <MyFramework/A.h>Objective-C访问它们

在Swift中,您仍然可以访问C代码,因为我们将头文件放在module.modulemap已复制到文件中MyFramework.framework/Modules/module.modulemap

幸运的是,我们可以通过一些后期处理来摆脱这两个问题:

  1. PrivateHeaders从框架捆绑包中删除文件夹。
  2. 创建一个单独的modulemap并删除所有header "XYZ.h"语句,例如,将其命名为public.modulemap
  3. 将所有这些置于Run Script构建阶段

这是公共模块图:

# public.modulemap

framework module MyFramework {

    umbrella header "MyFramework.h"  

    export *
    module * {export *}

    # No more C Headers here
}

以及应该添加到框架构建阶段末尾的运行脚本:

# Delete PrivateHeaders folder
rm -rf ${TARGET_BUILD_DIR}/${PRODUCT_NAME}${WRAPPER_SUFFIX}/PrivateHeaders

# Remove module.modulemap file
rm ${TARGET_BUILD_DIR}/${PRODUCT_NAME}${WRAPPER_SUFFIX}/Modules/module.modulemap

# Copy public.modulemap file and rename it to module.modulemap
cp ${SRCROOT}/test/public.modulemap ${TARGET_BUILD_DIR}/${PRODUCT_NAME}${WRAPPER_SUFFIX}/Modules/module.modulemap

# Append the Swift module so you can access you Swift code in Objective-C via @import MyFramework.Swift
echo "module ${PRODUCT_NAME}.Swift { header \"${PRODUCT_NAME}-Swift.h\" }" >> ${TARGET_BUILD_DIR}/${PRODUCT_NAME}${WRAPPER_SUFFIX}/Modules/module.modulemap

希望对您有所帮助!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何将源代码编译到内核中?

iOS Swift框架:如何将Objective C代码正确导入swift框架?

如何将源代码连接到Xcode中的已编译框架

C ++如何将源代码生成的映射包括到应用程序中以进行预编译阶段

如何将 Swing JPanel 嵌入到 JavaFX 框架中?

如何将页面对齐到WPF中的框架

如何将模型固定到框架中的相机?

如何将参数从Swift本机代码``放''到Flutter

如何将多个Rust文件编译到单个C库中?

如何将Swift代码转换为目标C代码

如何将 C 代码输出输入到 shell 脚本变量中

如何将多行代码复制到byebug中?

如何将数据从CSV文件输入到代码中?

python fabric如何将\输入到代码分支中

如何将汇编代码嵌入到php中?

如何将代码行绑定到 VSCode 中的值?

JNA如何将String []从Java传递到C代码

如何将paraview源代码编译到Qt项目(.pro)?

WebApp无法找到类型,如何将源代码编译到目标目录

如何将Swift代码导入Objective-C?

如何将代码保存在MVC实体框架的模型类中,甚至将类删除?

如何将文本文件作为const字符串编译到C ++程序中?

如何将swift类导入到ViewController中?

您如何将数据从Objective C传递到Swift?

如何将c,c ++和python代码编译为“已发布/最终”版本?

如何将代码块从组织模式导出到封装到框架中的pdf

pybind11:如何将c ++和python代码打包到一个包中?

如何将天蓝色存储实现到vaadin框架中

如何将 Mapbox iOS 框架集成到 Kotlin 原生中