Swift Achieved Dynamic Linking Where Rust Couldn't

This page summarizes the projects mentioned and recommended in the original post on news.ycombinator.com

Our great sponsors
  • InfluxDB - Power Real-Time Data Analytics at Scale
  • WorkOS - The modern identity platform for B2B SaaS
  • SaaSHub - Software Alternatives and Reviews
  • Lunar

    Intelligent adaptive brightness for your external monitors

  • This past week I’ve been reverse engineering the macOS IOMobileFramebuffer to find a way to disconnect displays in software for Lunar (https://lunar.fyi/).

    And I kept stumbling upon these witness tables while debugging.

    This led me to find this write-up and the much more interesting story behind it.

    The end note was priceless ^_^

    collapses

  • wasm-bindgen

    Facilitating high-level interactions between Wasm modules and JavaScript

  • Love the article.

    In my mind I see the problem of dynamic linking in rust to have a bunch of overlap with the "I want this rust library to be exposed in my higher level GC'd language with minimal safety/handwritten bindings" problem.

    My hunch is that the lack of expressiveness of the C ABI is holding back both. the thing I'd love to see some sort of "higher level than the C ABI" come out. And something like `wasm-bindgen`[0] to exist for more languages.

    Here's a link to the rust "interopable_api" proposal! I don't understand all the implications, but it seems to be in the right direction https://github.com/rust-lang/rust/pull/105586

    [0]https://rustwasm.github.io/docs/wasm-bindgen/

  • InfluxDB

    Power Real-Time Data Analytics at Scale. Get real-time insights from all types of time series data with InfluxDB. Ingest, query, and analyze billions of data points in real-time with unbounded cardinality.

    InfluxDB logo
  • rust

    Empowering everyone to build reliable and efficient software.

  • Love the article.

    In my mind I see the problem of dynamic linking in rust to have a bunch of overlap with the "I want this rust library to be exposed in my higher level GC'd language with minimal safety/handwritten bindings" problem.

    My hunch is that the lack of expressiveness of the C ABI is holding back both. the thing I'd love to see some sort of "higher level than the C ABI" come out. And something like `wasm-bindgen`[0] to exist for more languages.

    Here's a link to the rust "interopable_api" proposal! I don't understand all the implications, but it seems to be in the right direction https://github.com/rust-lang/rust/pull/105586

    [0]https://rustwasm.github.io/docs/wasm-bindgen/

  • Tokamak

    SwiftUI-compatible framework for building browser apps with WebAssembly and native apps for other platforms

  • swift

    The Swift Programming Language

  • They are exactly the same except for when they're not.

    (On 64-bit) Rust very naively has two 64-bit integers for the strong and weak count, Swift packs them into only one. Swift also packs in several extra flags for various things [0].

    These flags mean that retain/release (increment/decrement) is actually an atomic compare-and-swap instead of a fetch-add. Allegedly performance issues with this were fixed by the hardware team, just, optimizing CASes better.

    Swift also has to interop with ObjC "weak" pointers which have move constructors because their address is registered with a global map which is used to null them out when all strong counts go away, but I don't think this changes the design much when not using them.

    Swift ARC is built into the language and a huge amount of the compiler's energy is dedicated to optimizing it. This is why it's part of the calling convention (+1/+0), why there are special getter/setter modes with different ARC semantics, why many stdlib functions are annotated with "this has such-and-such semantics" and so on.

    Swift ARC is also very pervasive, as basic collections are all ARC-based CoW, all classes are ARC, and I think existentials and implicit boxes also go through ARC for uniformity?

    ARC is also why historically Swift gave itself fairly extreme leniency on running destructors "early" based on actual use [1]. Eliminating a useless +1 can be the difference between O(n) and O(n^2) once CoW gets involved!

    By contrast in Rust it's "just" a library type which you have to clone/drop (increment/decrement) manually. It doesn't do anything particularly special, but it's very predictable. The existence of borrows in Rust lets you manually do +0 semantics without having to rely on the compiler noticing the optimization opportunity, although you do need to convince the borrow checker it's correct.

    [0]: https://github.com/apple/swift/blob/3b00177f768b630a8f7a1135...

    [1]: https://forums.swift.org/t/a-roadmap-for-improving-swift-per...

  • CppCoreGuidelines

    The C++ Core Guidelines are a set of tried-and-true guidelines, rules, and best practices about coding in C++

  • There are many differences when it comes to safety:

    - Like you said, Rust doesn't let you data race on the contents of an Arc.

    - Rust also doesn't let you data race on the Arc _itself_ (i.e. repointing a global Arc without synchronization). This is Bug #5 in this great talk: https://youtu.be/lkgszkPnV8g

    - Rust also doesn't let you retain a reference to the contents of an Arc longer than you retain the Arc. This is the bug that C++ Core Guideline R.37 is about: http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#...

    But I'm not sure I'd call these Arc vs shared_ptr differences per se, because almost any comparison between a Rust container and its C++ equivalent looks similar.

  • trivy

    Find vulnerabilities, misconfigurations, secrets, SBOM in containers, Kubernetes, code repositories, clouds and more

  • > and static compilation probably just hides the problem unless security scanners these days can identify statically compiled vulnerable versions of libraries

    Some scanners like trivy [1] can scan statically compiled binaries, provided they include dependency version information (I think go does this on its own, for rust there's [2], not sure about other languages).

    It also looks into your containers.

    The problem is what to do when it finds a vulnerability. In a fat app with dynamic linking you could exchange the offending library, check that this doesn't break anything for your use case, and be on your way. But with static linking you need to compile a new version, or get whoever can build it to compile a new version. Which seems to be a major drawback of discouraging fat apps.

    1: https://github.com/aquasecurity/trivy

    2: https://github.com/rust-secure-code/cargo-auditable

  • WorkOS

    The modern identity platform for B2B SaaS. The APIs are flexible and easy-to-use, supporting authentication, user identity, and complex enterprise features like SSO and SCIM provisioning.

    WorkOS logo
  • cargo-auditable

    Make production Rust binaries auditable

  • > and static compilation probably just hides the problem unless security scanners these days can identify statically compiled vulnerable versions of libraries

    Some scanners like trivy [1] can scan statically compiled binaries, provided they include dependency version information (I think go does this on its own, for rust there's [2], not sure about other languages).

    It also looks into your containers.

    The problem is what to do when it finds a vulnerability. In a fat app with dynamic linking you could exchange the offending library, check that this doesn't break anything for your use case, and be on your way. But with static linking you need to compile a new version, or get whoever can build it to compile a new version. Which seems to be a major drawback of discouraging fat apps.

    1: https://github.com/aquasecurity/trivy

    2: https://github.com/rust-secure-code/cargo-auditable

  • vst3sdk

    VST 3 Plug-In SDK

  • But you don't have only Linux, you have (and probably first) OSX and/or Windows and then Linux, and you need an API that works well in that case. Being an in-process dll/so plugin, while fraught with perils gets you to avoid other issues (state, health, restart, identity, etc.)

    Also sometimes you don't have a choice, but have to make a dll, for example:

    https://github.com/steinbergmedia/vst3sdk or https://ae-plugins.docsforadobe.dev/ and many others. Sometimes it's the only viable choice.

    (I wish most have used grpc/flatbuffers/whatever to communicate, but then every RPC call have to be checked/retried/handled, and or shared memory well handled, with (?) locks, etc. - not a trivial thing for someone who is deeply specialized in making a very good effect/renderer/etc instead of dealing with this extra complexity on top).

  • I use a Python script to read the shared memory and generate JSON with this information, then a web page using this JSON is overlaid using OBS, and this way we transmit races on YouTube.

    Here is how it looks like: https://youtu.be/ijSL8uN8cIw?t=5582

    If you want to read about a public project that uses this strategy, here is the repository link:

    https://gitlab.com/winzarten/SecondMonitor

    I don't know C#, but it should work similarly. This also means you definitely don't need to use the same language to create and to consume the information.

NOTE: The number of mentions on this list indicates mentions on common posts plus user suggested alternatives. Hence, a higher number means a more popular project.

Suggest a related project

Related posts