{"id":18041615,"url":"https://github.com/katyo/extern_executor","last_synced_at":"2025-08-17T05:05:42.438Z","repository":{"id":57627007,"uuid":"256496058","full_name":"katyo/extern_executor","owner":"katyo","description":"Rust async executor which delegates execution to external event loop","archived":false,"fork":false,"pushed_at":"2023-06-17T10:40:13.000Z","size":84,"stargazers_count":5,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-18T15:23:46.648Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/katyo.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-17T12:25:02.000Z","updated_at":"2024-02-05T07:21:57.000Z","dependencies_parsed_at":"2025-04-09T19:23:05.404Z","dependency_job_id":"6cde7fc1-7070-4583-82fc-db692150c611","html_url":"https://github.com/katyo/extern_executor","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/katyo/extern_executor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katyo%2Fextern_executor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katyo%2Fextern_executor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katyo%2Fextern_executor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katyo%2Fextern_executor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/katyo","download_url":"https://codeload.github.com/katyo/extern_executor/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katyo%2Fextern_executor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270807934,"owners_count":24649346,"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","status":"online","status_checked_at":"2025-08-17T02:00:09.016Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2024-10-30T16:11:00.426Z","updated_at":"2025-08-17T05:05:42.413Z","avatar_url":"https://github.com/katyo.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# External executor for async Rust\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)\n[![Crates.io Package](https://img.shields.io/crates/v/extern_executor.svg?style=popout)](https://crates.io/crates/extern_executor)\n[![Docs.rs API Docs](https://docs.rs/extern_executor/badge.svg)](https://docs.rs/extern_executor)\n[![Travis-CI Status](https://travis-ci.com/katyo/extern_executor.svg?branch=master)](https://travis-ci.com/katyo/extern_executor)\n\nThis project aims to provide simple executor which helps to delegate running asynchronous Rust code to external event loops.\nAs example, it may be useful in case when you develop dynamic linked libraries which have async code in Rust and want to run it in different execution environments.\n\n## Usage\n\nOn a Rust side you should add `extern_executor` as dependency to your `cdylib` crate and use `spawn()` function to run futures, like so:\n\n```rust\nuse extern_executor::spawn;\n\nspawn(async {\n  // your awaits\n});\n```\n\nOn a C side you should implement executor's driver using your preferred event loop API.\nFor example, when [libuv](https://github.com/libuv/libuv) is used it may looks like so:\n\n```c\n#include \u003cuv.h\u003e\n#include \u003crust_async_executor.h\u003e\n\nstatic void task_wake(RustAsyncExecutorExternTask data) {\n    uv_async_t* handle = data;\n    // wakeup uv's async task\n    uv_async_send(handle);\n}\n\nstatic void task_poll(uv_async_t* handle) {\n    // poll internal task until task complete\n    if (!rust_async_executor_poll(handle-\u003edata)) {\n        // drop internal task when task complete\n        rust_async_executor_drop(handle-\u003edata);\n        // drop uv's async task handle\n        uv_close((uv_handle_t*)handle, NULL);\n    }\n}\n\nstatic RustAsyncExecutorExternTask\ntask_new(RustAsyncExecutorUserData data) {\n    uv_loop_t* loop = data;\n    // crate and initialize uv's async task handle\n    uv_async_t* handle = malloc(sizeof(uv_async_t));\n    uv_async_init(loop, handle, task_poll);\n    return handle;\n}\n\nstatic void task_run(RustAsyncExecutorExternTask task,\n                     RustAsyncExecutorInternTask data) {\n    uv_async_t* handle = task;\n    // store internal task handle to be able to poll it later\n    handle-\u003edata = data;\n    uv_async_send(handle); // do initial polling (important)\n}\n\nvoid uv_rust_async_executor_init(uv_loop_t *loop) {\n    // send out executor API to Rust side\n    rust_async_executor_init(task_new, task_run, task_wake, loop);\n}\n```\n\nNow you can run your async code in __libuv__'s event loop like so:\n\n```c\nint main(void) {\n    uv_loop_t loop;\n\n    uv_loop_init(\u0026loop);\n    uv_rust_async_executor_init(\u0026loop);\n\n    my_async_function(my_async_callback);\n\n    uv_run(\u0026loop, UV_RUN_DEFAULT);\n    uv_loop_close(\u0026loop);\n\n    return 0;\n}\n```\n\nThe C header _rust_async_executor.h_ generated using [cbindgen](https://github.com/eqrion/cbindgen/).\nThere are two options how you can get it:\n\n* Copy from _include_ directory in this repo\n* Generate by youself by using _cbindgen_ feature\n\nIn second case generated header will be available at `target/$PROFILE/include` directory.\n\n## Built-in event-loop drivers\n\nTo simplify setup for some widely used event loops the built-in drivers was introduced.\nTo use driver you should enable corresponding feature. Currently supported next drivers:\n\n- __uv__ built-in _libuv_ event loop integration (see [example_uv](http://github.com/katyo/extern_executor/tree/master/example_uv))\n- __dart__ built-in _dart-lang_ event loop integration (see [example_dart](http://github.com/katyo/extern_executor/tree/master/example_uv))\n\n## Linking issues\n\nRust currently have an issues related to re-exporting of symbols from crate's dependencies (#[2771](https://github.com/rust-lang/rfcs/issues/2771)).\n\nAs temporary solution you can setup build profile like so:\n\n```toml\n[profile.release]\nlto = true\nincremental = false\n```\n\n## Tokio compatibility\n\nThis executor incompatible with [tokio](https://github.com/tokio-rs/tokio)'s futures because _tokio_ still has non-trivial executor which mixed with reactor.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkatyo%2Fextern_executor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkatyo%2Fextern_executor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkatyo%2Fextern_executor/lists"}