这是关于使用 Haskell 和 Swift/SwiftUI 开发原生 macOS 和 iOS 应用的深入系列博客文章的第二篇。主要内容如下:
- 介绍(Introduction):从上一篇文章结束的地方开始,已设置包含从 Haskell 模块生成的头文件并链接到 cabal 文件中声明的外部库的 XCode 项目,能从 Swift 中通过 Haskell 的 C 外部导出功能调用简单的 Haskell 函数,此部分关注从 Swift 调用惯用的 Haskell 函数,包括将用户定义的数据类型作为输入和输出,并将其以透明方式提供给 Swift。例如通过
birthday
函数展示从 Haskell 到 Swift 的暴露方法,为此需要在 Haskell 和 Swift 之间转换User
数据类型,将函数的大部分输入和输出序列化,添加User
数据类型和birthday
函数到相应文件。 - 输入和输出的封送处理(Marshaling Inputs and Outputs):从 Swift 角度看,封送函数的输入和输出意味着将输入值序列化为字符串,将输出值作为字符串接收,然后将其解码为 Swift 值,Haskell 视角与之相反。将使用与从天堂调用炼狱:在 Haskell 中绑定到 Rust相同的封送处理策略,以
JSON
作为序列化格式,Haskell 方面需使User
可解码,扩展User
示例需添加相关扩展和导入必要模块,导出c_birthday
函数并将其作为 C 函数供 Swift 使用。在 Swift 方面,要使User
可 JSON 编码/解码,实现birthday
函数调用c_birthday
,处理参数和结果的序列化与反序列化,包括获取和使用指针、处理缓冲区大小等,若序列化结果超出缓冲区大小需重试。 边界处的元编程(Metaprogramming at the boundaries):
- Haskell 的视角(Haskell’s perspective):通过
foreignExportSwift
Template Haskell 函数暴露birthday
函数,使用特定的调用约定进行封送处理。 - Swift 的视角(Swift’s perspective):使用
@ForeignImportHaskell
宏生成 Swift 函数包装器,调用 Haskell 暴露的 C 函数,通过这种封送处理策略实现跨语言边界的调用。
- Haskell 的视角(Haskell’s perspective):通过
- 备注(Remarks):介绍了使用编译时代码生成功能(Haskell 的 Template Haskell 和 Swift 的 Swift Macros)的预览,还将探讨从 Swift 调用 Haskell 的其他方式,如强制将 Haskell 值的内存表示转换为 Swift 值等,并提到haskell-x-swift-project-steps仓库与指南步骤匹配,此项目部分由Well-Typed赞助,可访问我的 GitHub 赞助页面赞助相关工作。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。