{"id":18338612,"url":"https://github.com/mqnfred/dustr","last_synced_at":"2025-04-06T05:31:47.186Z","repository":{"id":57622410,"uuid":"257992895","full_name":"mqnfred/dustr","owner":"mqnfred","description":"Dart - rust - Flutter compatibility","archived":false,"fork":false,"pushed_at":"2020-07-04T03:18:50.000Z","size":170,"stargazers_count":47,"open_issues_count":1,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-28T22:13:45.572Z","etag":null,"topics":["dart","ffi","flutter","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mqnfred.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-22T18:56:47.000Z","updated_at":"2024-12-20T05:07:31.000Z","dependencies_parsed_at":"2022-09-26T20:10:41.750Z","dependency_job_id":null,"html_url":"https://github.com/mqnfred/dustr","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mqnfred%2Fdustr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mqnfred%2Fdustr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mqnfred%2Fdustr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mqnfred%2Fdustr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mqnfred","download_url":"https://codeload.github.com/mqnfred/dustr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247440346,"owners_count":20939221,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dart","ffi","flutter","rust"],"created_at":"2024-11-05T20:14:43.376Z","updated_at":"2025-04-06T05:31:46.590Z","avatar_url":"https://github.com/mqnfred.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DUSTR\n\nWith `dustr`, you can call this rust code:\n\n```rust\n#[derive(FFIShim)]\nstruct User {\n    name: String,\n}\n\n#[ffishim_function]\nfn hello(u: User) -\u003e String {\n    format!(\"Hello, {}!\", u.name)\n}\n```\n\nfrom dart:\n\n```dart\nimport 'package:hello/hello.dart';\n\nvoid main() {\n    var greeting = hello(User.build(\"fred\"));\n    print(\"${greeting}\");\n}\n```\n\n`dustr` is a binary that parses rust code to generate its dart bindings. The\nrust code must be marked using the [ffishim_derive][1] procedural macros from\nthe [ffishim][4] library.\n\nThese procedural macros generate an FFI-compatible API around the original data\nstructure/function. This is necessary because many basic rust types (`String`,\n`Option`, `Vec`, ...) do not respect the C ABI.\n\n## Install \u0026 usage\n\nNow, suppose we want to reproduce our first example. We need make, cargo and\nthe dart sdk. We install dustr using cargo:\n\n```sh\nexport PATH=$PATH:$HOME/.cargo/bin\ncargo install dustr\n```\n\nWe also create our hello crate which we will mark as C dynamic library (cdylib,\nto generate a `.so` shared object in the `rusthello/target/debug` directory.)\n\n```sh\ncargo new --lib rusthello --name hello\ncat \u003e\u003erusthello/Cargo.toml \u003c\u003cEOF\nffishim = \"^0\"\nffishim_derive = \"^0\"\n\n[lib]\ncrate-type = [\"cdylib\"]\nEOF\ncat \u003erusthello/src/lib.rs \u003c\u003cEOF\n#[macro_use]\nextern crate ffishim_derive;\n\n#[derive(FFIShim)]\nstruct User {\n    name: String,\n}\n\n#[ffishim_function]\nfn hello(u: User) -\u003e String {\n    format!(\"Hello, {}!\", u.name)\n}\nEOF\ncargo build --manifest-path=rusthello/Cargo.toml\nls rusthello/target/debug/libhello.so\n```\n\nWe took the opportunity to add the code (with a healthy dose more plumbing this\ntime) and build the library. Now let's step into the dart side...\n\n```sh\ndustr --dest darthello --name hello rusthello/\ncd darthello; pub get; cd -\n```\n\nThe `dustr` command will create the dart package containing the bindings to the\nrusthello library. `pub get` pulls in any dependencies. We'll now set up the\ndart app which will use our bindings:\n\n```sh\nmkdir -p dartapp/bin\ncat \u003edartapp/bin/main.dart \u003c\u003cEOF\nimport 'package:hello/hello.dart';\n\nvoid main() {\n    var greeting = hello(User.build(\"fred\"));\n    print(\"\\${greeting}\");\n}\nEOF\ncat \u003edartapp/pubspec.yaml \u003c\u003cEOF\n---\nname: app\ndependencies:\n  hello:\n    path: ../darthello\nenvironment:\n  sdk: \"\u003e=2.0.0 \u003c3.0.0\"\nEOF\ncd dartapp; pub get; cd -\n```\n\nNow we can run the app. Don't forget to provide the rust library:\n\n```sh\nLD_LIBRARY_PATH=rusthello/target/debug dart dartapp/bin/main.dart\n```\n\n## Examples\n\nYou can find examples of `dustr`'s behavior by looking at the [`tests`][1]\nfolder. The structure of the tests are as follow:\n\n - `src/lib.rs`: the rust library to expose\n - `Cargo.toml`: manifest of the rust library (defines cdylib, etc..)\n - `pubspec.yaml`: manifest of dart binary (defines dep on generated bindings)\n - `bin/main.dart`: the dart code that uses this rust library\n - `expected_output`: contains the output expected from running the C program\n\nEvery test folder is a stand-alone app. For example, you could:\n\n - Run `make` to test all of them\n - Inspect the generated bindings code in the `target/bindings` hierarchy\n - Tweak a test or two to try out behavior and rerun `make` to test things out\n - Use them as templates to create your own working rust \u003c-\u003e dart integration\n\n## C ABI Disclaimer\n\nBecause dart ffi support is still in alpha, it cannot quite consume the C ABI\njust yet. For example, [it does not support nested structs][2], and [structures\ncannot be passed by value to functions][3]. For this reason, the ffishim crate\nwe use does not generate C-ABI code exactly, but a bastard version consumable\nby the dart ffi.\n\n## TODO/Limitations\n\nThis crate is still in beta. It is not fit for production use yet.\n\n### Bugs\n\n - Fix leaking of returned strings when not inside struct/enum\n - Fix leaking of returned options when not inside struct/enum\n\n### Features\n\n - Adapt to potential name mangling in ffishim (to avoid duplicates)\n - Find equivalent dart type for usize/isize/char\n - Implement DateTime behavior\n\n### Testing\n\n - Add a \"complete\" test/example situation\n - Re-organize tests by domain (find taxonomy)\n - Benchmark some use-cases\n\n### Documentation\n\n - Write README.md introduction on what this crate does\n - Where to write binary documentation in doc.rs?\n\n[1]: https://docs.rs/ffishim_derive/0.1.2/ffishim_derive\n[2]: https://github.com/dart-lang/sdk/issues/37271\n[3]: https://github.com/dart-lang/sdk/issues/41062\n[4]: https://github.com/mqnfred/ffishim\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmqnfred%2Fdustr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmqnfred%2Fdustr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmqnfred%2Fdustr/lists"}