RubyGateway 5.5.0

RubyGateway 5.5.0

John Fairhurst 维护。



  • John Fairhurst

RubyGateway

CI codecov Carthage compatible Pod Platforms License

在 Swift 中嵌入 Ruby:加载 Gems、运行 Ruby 脚本、无缝调用 API(双向)。

RubyGateway 是一个基于 Ruby C API 的框架,使在 macOS 或 Linux 上运行的 Swift 程序可以轻松且安全地运行和交互 Ruby 程序。它很容易将 Swift 值传递到 Ruby,并将 Ruby 对象转换回 Swift 类型。

RubyGateway 允许您从 Swift 调用任何 Ruby 方法,包括传递 Swift 闭包作为块。它允许您定义在 Swift 中实现的 Ruby 类和方法。

如果您正在寻找低级别的 Ruby C API 包装器,请参见 CRuby

示例

服务

Rouge 是一个代码高亮工具。在 Ruby

require 'rouge'
html = Rouge.highlight("let a = 3", "swift", "html")
puts(html)

在 Swift 中

import RubyGateway

try Ruby.require(filename: "rouge")
let html = try Ruby.get("Rouge").call("highlight", args: ["let a = 3", "swift", "html"])
print(html)

调用 Ruby

// Create an object.  Use keyword arguments with initializer
let student = RbObject(ofClass: "Academy::Student", kwArgs: ["name": "barney"])!

// Acess an attribute
print("Name is \(student.get("name"))")

// Fix their name by poking an ivar
try! student.setInstanceVar("@name", newValue: "Barney")

// Get a Swift version of `:reading`
let readingSubject = RbSymbol("reading")

// Call a method with mixed Swift data types
try! student.call("add_score", args: [readingSubject, 30])
try! student.call("add_score", args: [readingSubject, 35])

// Get a result as floating point
let avgScoreObj = try! student.call("mean_score_for_subject", args: [readingSubject])
let avgScore = Double(avgScoreObj)!
print("Mean score is \(avgScore)")

// Pass Swift code as a block
let scores = student.all_scores!
scores.call("each") { args in
    print("Subject: \(args[0]) Score: \(args[1])")
    return .nilObject
}

// Convert to a Swift array
let subjects = Array<String>(student.all_subjects!)
subjectsPopularityDb.submit(subjects: subjects)

调用Swift

绑定类定义

class Cell {
    init() {
    }

    func setup(m: RbMethod) throws {
        ...
    }
    
    func getContent(m: RbMethod) throws -> String {
        ...
    }
}

let cellClass = try Ruby.defineClass("Cell", initializer: Cell.init)

try cellClass.defineMethod("initialize",
        argsSpec: RbMethodArgsSpec(mandatoryKeywords: ["width", "height"])
        method: Cell.setup)

try cellClass.defineMethod("content",
        argsSpec: RbMethodArgsSpec(requiresBlock: true),
        method: Cell.getContent)

从Ruby调用

cell = Cell.new(width: 200, height: 100)
cell.content { |c| prettyprint(c) }

全局变量

// epochStore.current: Int

Ruby.defineGlobalVar("$epoch",
        get: { epochStore.current },
        set: { epochStore.current = newEpoch })

全局函数

let logArgsSpec = RbMethodArgsSpec(leadingMandatoryCount: 1,
                                   optionalKeywordValues: ["priority" : 0])
try Ruby.defineGlobalFunction("log",
                              argsSpec: logArgsSpec) { _, method in
    Logger.log(message: String(method.args.mandatory[0]),
               priority: Int(method.args.keyword["priority"]!))
    return .nilObject
}

从Ruby调用

log(object_to_log)
log(object2_to_log, priority: 2)

文档

需求

  • Swift 5.4或更高版本,从swift.org或Xcode 12.5
  • macOS(已在12.6上测试)或Linux(已在Ubuntu Bionic/18.04 x86_64上测试)带有Clang 6。
  • Ruby 2.6或更高版本包括开发文件
    • 对于macOS,这些与Xcode一同提供。
    • 对于Linux,根据Ruby的安装方式,可能需要安装-dev包。
    • RubyGateway需要'original' MRI/CRuby Ruby - 不允许使用JRuby/Rubinius等。

由于Ruby 3.2,Ruby 3的Xcode项目存在问题:Xcode中运行测试时显示各种奇怪的错误,看起来像是链接问题,但在SPM中正常运行时不存在。

安装

对于macOS,如果您愿意使用系统Ruby,只需将RubyGateway框架作为一个依赖项包括即可。如果您在Linux上构建或想使用不同的Ruby,还需要配置CRuby。

如果您使用Ruby 3,需要在Swift PM命令行(swift build -Xcc -fdeclspec)或在Xcode的《其他Swift标志》设置中设置-fdeclspec Clang标志。

获取框架

Carthage for macOS

github "johnfairh/RubyGateway"

Swift 包管理器,适用于 macOS 或 Linux

.package(url: "https://github.com/johnfairh/RubyGateway", from: "5.4.0")

CocoaPods for macOS

pod 'RubyGateway'

配置 CRuby

CRuby 是 RubyGateway 与您的 Ruby 安装之间的粘合剂。这是一个独立的 GitHub 项目,但 RubyGateway 作为子模块包含它,因此您无需单独安装或要求它。

默认情况下,它指向 macOS 系统版 Ruby。按照 CRuby 使用说明 更改这一点。例如,在 Ubuntu 18 上使用 rbenv Ruby 3

mkdir MyProject && cd MyProject
swift package init --type executable
vi Package.swift
# add RubyGateway as a package dependency (NOT CRuby)
# add RubyGateway as a target dependency
echo "import RubyGateway; print(Ruby.versionDescription)" > Sources/MyProject/main.swift
swift package update
swift package edit CRuby
Packages/CRuby/cfg-cruby --mode rbenv --name 3.0.0
PKG_CONFIG_PATH=$(pwd)/Packages/CRuby:$PKG_CONFIG_PATH swift run -Xcc -fdeclspec

贡献

欢迎:提交问题 / [email protected] / @johnfairh

许可协议

在 MIT 许可协议下分发。