All Projects → johnfairh → RubyGateway

johnfairh / RubyGateway

Licence: other
Embed Ruby in Swift: load Gems, run scripts, call APIs seamlessly in both directions.

Programming Languages

swift
15916 projects
objective c
16641 projects - #2 most used programming language
ruby
36898 projects - #4 most used programming language
c
50402 projects - #5 most used programming language

Projects that are alternatives of or similar to RubyGateway

Xamarin.bindings
A list of existing Xamarin binding libraries.
Stars: ✭ 146 (+35.19%)
Mutual labels:  bindings
Qt5.cr
Qt5 bindings for Crystal, based on Bindgen
Stars: ✭ 182 (+68.52%)
Mutual labels:  bindings
Freetype Py
Python binding for the freetype library
Stars: ✭ 209 (+93.52%)
Mutual labels:  bindings
Piecash
Pythonic interface to GnuCash SQL documents
Stars: ✭ 172 (+59.26%)
Mutual labels:  bindings
Tdl
Node.js bindings to TDLib.
Stars: ✭ 177 (+63.89%)
Mutual labels:  bindings
Go Python3
Go bindings to the CPython-3 API
Stars: ✭ 185 (+71.3%)
Mutual labels:  bindings
Gintro
High level GObject-Introspection based GTK3/GTK4 bindings for Nim language
Stars: ✭ 141 (+30.56%)
Mutual labels:  bindings
Fltk Rs
Rust bindings for the FLTK GUI library.
Stars: ✭ 241 (+123.15%)
Mutual labels:  bindings
Rust Bindgen
Automatically generates Rust FFI bindings to C (and some C++) libraries.
Stars: ✭ 2,453 (+2171.3%)
Mutual labels:  bindings
Intercept
A C/C++ Binding Library for SQF and RV Engine Access Abstraction Layer
Stars: ✭ 191 (+76.85%)
Mutual labels:  bindings
Net Vips
.NET binding for libvips
Stars: ✭ 173 (+60.19%)
Mutual labels:  bindings
Cppsharp
Tools and libraries to glue C/C++ APIs to high-level languages
Stars: ✭ 2,221 (+1956.48%)
Mutual labels:  bindings
Libvlc Go
Go bindings for libVLC and high-level media player interface
Stars: ✭ 188 (+74.07%)
Mutual labels:  bindings
Python Sfml
Official binding of SFML for Python
Stars: ✭ 145 (+34.26%)
Mutual labels:  bindings
Nimgl
NimGL is a Nim library that offers bindings for popular libraries used in computer graphics
Stars: ✭ 218 (+101.85%)
Mutual labels:  bindings
Gopherjs Vue
VueJS bindings for gopherjs
Stars: ✭ 142 (+31.48%)
Mutual labels:  bindings
Vsphere Automation Sdk Rest
REST (Postman and JavaScript) samples and API reference documentation for vSphere using the VMware REST API
Stars: ✭ 182 (+68.52%)
Mutual labels:  bindings
Python Mpv
Python interface to the awesome mpv media player
Stars: ✭ 245 (+126.85%)
Mutual labels:  bindings
Vue Firestore
☁️ Cloud Firestore binding in realtime with Vuejs
Stars: ✭ 239 (+121.3%)
Mutual labels:  bindings
Widgetkit
Compose native apps without a code using JSON and load them as NSBundle into another app dynamicly from local or remote locations.
Stars: ✭ 191 (+76.85%)
Mutual labels:  bindings

RubyGateway

CI codecov Carthage compatible Pod Platforms License

Embed Ruby in Swift: load Gems, run Ruby scripts, invoke APIs seamlessly in both directions.

RubyGateway is a framework built on the Ruby C API that lets Swift programs running on macOS or Linux painlessly and safely run and interact with Ruby programs. It's easy to pass Swift values into Ruby and turn Ruby objects back into Swift types.

RubyGateway lets you call any Ruby method from Swift, including passing Swift closures as blocks. It lets you define Ruby classes and methods that are implemented in Swift.

See CRuby if you are looking for a low-level Ruby C API wrapper.

Examples

Services

Rouge is a code highlighter. In Ruby:

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

In Swift:

import RubyGateway

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

Calling 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)

Calling Swift

Bound class definition:

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)

Called from Ruby:

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

Global variables:

// epochStore.current: Int

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

Global functions:

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
}

Calls from Ruby:

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

Documentation

Requirements

  • Swift 5.4 or later, from swift.org or Xcode 12.5+
  • macOS (tested on 12.6) or Linux (tested on Ubuntu Bionic/18.04 on x86_64) with Clang 6.
  • Ruby 2.6 or later including development files:
    • For macOS, these come with Xcode.
    • For Linux you may need to install a -dev package depending on how your Ruby is installed.
    • RubyGateway requires 'original' MRI/CRuby Ruby - no JRuby/Rubinius/etc.

There's something wrong with the Ruby 3 Xcode project since Ruby 3.2: running tests in Xcode shows all kinds of weird errors that look like a linking problem that is not present run normally in SPM.

Installation

For macOS, if you are happy to use the system Ruby then you just need to include the RubyGateway framework as a dependency. If you are building on Linux or want to use a different Ruby then you also need to configure CRuby.

If you are using Ruby 3 then you need to set the -fdeclspec Clang flag, either on the Swift PM command line (swift build -Xcc -fdeclspec) or in Xcode's Other Swift Flags settings.

Getting the framework

Carthage for macOS:

github "johnfairh/RubyGateway"

Swift package manager for macOS or Linux:

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

CocoaPods for macOS:

pod 'RubyGateway'

Configuring CRuby

CRuby is the glue between RubyGateway and your Ruby installation. It is a separate github project but RubyGateway includes it as submodule so you do not install or require it separately.

By default it points to the macOS system Ruby. Follow the CRuby usage instructions to change this. For example on Ubuntu 18 using 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

Contributions

Welcome: open an issue / [email protected] / @johnfairh

License

Distributed under the MIT license.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].